target/arm: Update find_last_active for PREDDESC
[qemu/ar7.git] / hw / block / nvme-ns.h
blob318d3aebe1a8a7948e28f623d513b0faa065e9a9
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 #define TYPE_NVME_NS "nvme-ns"
19 #define NVME_NS(obj) \
20 OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
22 typedef struct NvmeZone {
23 NvmeZoneDescr d;
24 uint64_t w_ptr;
25 QTAILQ_ENTRY(NvmeZone) entry;
26 } NvmeZone;
28 typedef struct NvmeNamespaceParams {
29 bool detached;
30 uint32_t nsid;
31 QemuUUID uuid;
33 uint16_t mssrl;
34 uint32_t mcl;
35 uint8_t msrc;
37 bool zoned;
38 bool cross_zone_read;
39 uint64_t zone_size_bs;
40 uint64_t zone_cap_bs;
41 uint32_t max_active_zones;
42 uint32_t max_open_zones;
43 uint32_t zd_extension_size;
44 } NvmeNamespaceParams;
46 typedef struct NvmeNamespace {
47 DeviceState parent_obj;
48 BlockConf blkconf;
49 int32_t bootindex;
50 int64_t size;
51 NvmeIdNs id_ns;
52 const uint32_t *iocs;
53 uint8_t csi;
55 NvmeSubsystem *subsys;
56 QTAILQ_ENTRY(NvmeNamespace) entry;
58 NvmeIdNsZoned *id_ns_zoned;
59 NvmeZone *zone_array;
60 QTAILQ_HEAD(, NvmeZone) exp_open_zones;
61 QTAILQ_HEAD(, NvmeZone) imp_open_zones;
62 QTAILQ_HEAD(, NvmeZone) closed_zones;
63 QTAILQ_HEAD(, NvmeZone) full_zones;
64 uint32_t num_zones;
65 uint64_t zone_size;
66 uint64_t zone_capacity;
67 uint32_t zone_size_log2;
68 uint8_t *zd_extensions;
69 int32_t nr_open_zones;
70 int32_t nr_active_zones;
72 NvmeNamespaceParams params;
74 struct {
75 uint32_t err_rec;
76 } features;
77 } NvmeNamespace;
79 static inline uint32_t nvme_nsid(NvmeNamespace *ns)
81 if (ns) {
82 return ns->params.nsid;
85 return -1;
88 static inline bool nvme_ns_shared(NvmeNamespace *ns)
90 return !!ns->subsys;
93 static inline NvmeLBAF *nvme_ns_lbaf(NvmeNamespace *ns)
95 NvmeIdNs *id_ns = &ns->id_ns;
96 return &id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)];
99 static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns)
101 return nvme_ns_lbaf(ns)->ds;
104 /* calculate the number of LBAs that the namespace can accomodate */
105 static inline uint64_t nvme_ns_nlbas(NvmeNamespace *ns)
107 return ns->size >> nvme_ns_lbads(ns);
110 /* convert an LBA to the equivalent in bytes */
111 static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba)
113 return lba << nvme_ns_lbads(ns);
116 typedef struct NvmeCtrl NvmeCtrl;
118 static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone)
120 return zone->d.zs >> 4;
123 static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state)
125 zone->d.zs = state << 4;
128 static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone)
130 return zone->d.zslba + ns->zone_size;
133 static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone)
135 return zone->d.zslba + zone->d.zcap;
138 static inline bool nvme_wp_is_valid(NvmeZone *zone)
140 uint8_t st = nvme_get_zone_state(zone);
142 return st != NVME_ZONE_STATE_FULL &&
143 st != NVME_ZONE_STATE_READ_ONLY &&
144 st != NVME_ZONE_STATE_OFFLINE;
147 static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns,
148 uint32_t zone_idx)
150 return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size];
153 static inline void nvme_aor_inc_open(NvmeNamespace *ns)
155 assert(ns->nr_open_zones >= 0);
156 if (ns->params.max_open_zones) {
157 ns->nr_open_zones++;
158 assert(ns->nr_open_zones <= ns->params.max_open_zones);
162 static inline void nvme_aor_dec_open(NvmeNamespace *ns)
164 if (ns->params.max_open_zones) {
165 assert(ns->nr_open_zones > 0);
166 ns->nr_open_zones--;
168 assert(ns->nr_open_zones >= 0);
171 static inline void nvme_aor_inc_active(NvmeNamespace *ns)
173 assert(ns->nr_active_zones >= 0);
174 if (ns->params.max_active_zones) {
175 ns->nr_active_zones++;
176 assert(ns->nr_active_zones <= ns->params.max_active_zones);
180 static inline void nvme_aor_dec_active(NvmeNamespace *ns)
182 if (ns->params.max_active_zones) {
183 assert(ns->nr_active_zones > 0);
184 ns->nr_active_zones--;
185 assert(ns->nr_active_zones >= ns->nr_open_zones);
187 assert(ns->nr_active_zones >= 0);
190 int nvme_ns_setup(NvmeNamespace *ns, Error **errp);
191 void nvme_ns_drain(NvmeNamespace *ns);
192 void nvme_ns_shutdown(NvmeNamespace *ns);
193 void nvme_ns_cleanup(NvmeNamespace *ns);
195 #endif /* NVME_NS_H */