Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210330' into...
[qemu/ar7.git] / hw / block / nvme-ns.h
blob9ab7894fc83e6b96be41ac913adc92401c65b407
1 /*
2 * QEMU NVM Express Virtual Namespace
4 * Copyright (c) 2019 CNEX Labs
5 * Copyright (c) 2020 Samsung Electronics
7 * Authors:
8 * Klaus Jensen <k.jensen@samsung.com>
10 * This work is licensed under the terms of the GNU GPL, version 2. See the
11 * COPYING file in the top-level directory.
15 #ifndef NVME_NS_H
16 #define NVME_NS_H
18 #include "qemu/uuid.h"
20 #define TYPE_NVME_NS "nvme-ns"
21 #define NVME_NS(obj) \
22 OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
24 typedef struct NvmeZone {
25 NvmeZoneDescr d;
26 uint64_t w_ptr;
27 QTAILQ_ENTRY(NvmeZone) entry;
28 } NvmeZone;
30 typedef struct NvmeNamespaceParams {
31 bool detached;
32 uint32_t nsid;
33 QemuUUID uuid;
35 uint16_t ms;
36 uint8_t mset;
37 uint8_t pi;
38 uint8_t pil;
40 uint16_t mssrl;
41 uint32_t mcl;
42 uint8_t msrc;
44 bool zoned;
45 bool cross_zone_read;
46 uint64_t zone_size_bs;
47 uint64_t zone_cap_bs;
48 uint32_t max_active_zones;
49 uint32_t max_open_zones;
50 uint32_t zd_extension_size;
51 } NvmeNamespaceParams;
53 typedef struct NvmeNamespace {
54 DeviceState parent_obj;
55 BlockConf blkconf;
56 int32_t bootindex;
57 int64_t size;
58 int64_t mdata_offset;
59 NvmeIdNs id_ns;
60 const uint32_t *iocs;
61 uint8_t csi;
62 uint16_t status;
64 NvmeSubsystem *subsys;
65 QTAILQ_ENTRY(NvmeNamespace) entry;
67 NvmeIdNsZoned *id_ns_zoned;
68 NvmeZone *zone_array;
69 QTAILQ_HEAD(, NvmeZone) exp_open_zones;
70 QTAILQ_HEAD(, NvmeZone) imp_open_zones;
71 QTAILQ_HEAD(, NvmeZone) closed_zones;
72 QTAILQ_HEAD(, NvmeZone) full_zones;
73 uint32_t num_zones;
74 uint64_t zone_size;
75 uint64_t zone_capacity;
76 uint32_t zone_size_log2;
77 uint8_t *zd_extensions;
78 int32_t nr_open_zones;
79 int32_t nr_active_zones;
81 NvmeNamespaceParams params;
83 struct {
84 uint32_t err_rec;
85 } features;
86 } NvmeNamespace;
88 static inline uint16_t nvme_ns_status(NvmeNamespace *ns)
90 return ns->status;
93 static inline uint32_t nvme_nsid(NvmeNamespace *ns)
95 if (ns) {
96 return ns->params.nsid;
99 return -1;
102 static inline bool nvme_ns_shared(NvmeNamespace *ns)
104 return !!ns->subsys;
107 static inline NvmeLBAF *nvme_ns_lbaf(NvmeNamespace *ns)
109 NvmeIdNs *id_ns = &ns->id_ns;
110 return &id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)];
113 static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns)
115 return nvme_ns_lbaf(ns)->ds;
118 /* convert an LBA to the equivalent in bytes */
119 static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba)
121 return lba << nvme_ns_lbads(ns);
124 static inline size_t nvme_lsize(NvmeNamespace *ns)
126 return 1 << nvme_ns_lbads(ns);
129 static inline uint16_t nvme_msize(NvmeNamespace *ns)
131 return nvme_ns_lbaf(ns)->ms;
134 static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba)
136 return nvme_msize(ns) * lba;
139 static inline bool nvme_ns_ext(NvmeNamespace *ns)
141 return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas);
144 /* calculate the number of LBAs that the namespace can accomodate */
145 static inline uint64_t nvme_ns_nlbas(NvmeNamespace *ns)
147 if (nvme_msize(ns)) {
148 return ns->size / (nvme_lsize(ns) + nvme_msize(ns));
150 return ns->size >> nvme_ns_lbads(ns);
153 typedef struct NvmeCtrl NvmeCtrl;
155 static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone)
157 return zone->d.zs >> 4;
160 static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state)
162 zone->d.zs = state << 4;
165 static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone)
167 return zone->d.zslba + ns->zone_size;
170 static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone)
172 return zone->d.zslba + zone->d.zcap;
175 static inline bool nvme_wp_is_valid(NvmeZone *zone)
177 uint8_t st = nvme_get_zone_state(zone);
179 return st != NVME_ZONE_STATE_FULL &&
180 st != NVME_ZONE_STATE_READ_ONLY &&
181 st != NVME_ZONE_STATE_OFFLINE;
184 static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns,
185 uint32_t zone_idx)
187 return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size];
190 static inline void nvme_aor_inc_open(NvmeNamespace *ns)
192 assert(ns->nr_open_zones >= 0);
193 if (ns->params.max_open_zones) {
194 ns->nr_open_zones++;
195 assert(ns->nr_open_zones <= ns->params.max_open_zones);
199 static inline void nvme_aor_dec_open(NvmeNamespace *ns)
201 if (ns->params.max_open_zones) {
202 assert(ns->nr_open_zones > 0);
203 ns->nr_open_zones--;
205 assert(ns->nr_open_zones >= 0);
208 static inline void nvme_aor_inc_active(NvmeNamespace *ns)
210 assert(ns->nr_active_zones >= 0);
211 if (ns->params.max_active_zones) {
212 ns->nr_active_zones++;
213 assert(ns->nr_active_zones <= ns->params.max_active_zones);
217 static inline void nvme_aor_dec_active(NvmeNamespace *ns)
219 if (ns->params.max_active_zones) {
220 assert(ns->nr_active_zones > 0);
221 ns->nr_active_zones--;
222 assert(ns->nr_active_zones >= ns->nr_open_zones);
224 assert(ns->nr_active_zones >= 0);
227 void nvme_ns_init_format(NvmeNamespace *ns);
228 int nvme_ns_setup(NvmeNamespace *ns, Error **errp);
229 void nvme_ns_drain(NvmeNamespace *ns);
230 void nvme_ns_shutdown(NvmeNamespace *ns);
231 void nvme_ns_cleanup(NvmeNamespace *ns);
233 #endif /* NVME_NS_H */