188eea45cSKlaus Jensen /*
288eea45cSKlaus Jensen * QEMU NVM Express
388eea45cSKlaus Jensen *
488eea45cSKlaus Jensen * Copyright (c) 2012 Intel Corporation
588eea45cSKlaus Jensen * Copyright (c) 2021 Minwoo Im
688eea45cSKlaus Jensen * Copyright (c) 2021 Samsung Electronics Co., Ltd.
788eea45cSKlaus Jensen *
888eea45cSKlaus Jensen * Authors:
988eea45cSKlaus Jensen * Keith Busch <kbusch@kernel.org>
1088eea45cSKlaus Jensen * Klaus Jensen <k.jensen@samsung.com>
1188eea45cSKlaus Jensen * Gollu Appalanaidu <anaidu.gollu@samsung.com>
1288eea45cSKlaus Jensen * Dmitry Fomichev <dmitry.fomichev@wdc.com>
1388eea45cSKlaus Jensen * Minwoo Im <minwoo.im.dev@gmail.com>
1488eea45cSKlaus Jensen *
1588eea45cSKlaus Jensen * This code is licensed under the GNU GPL v2 or later.
1688eea45cSKlaus Jensen */
1788eea45cSKlaus Jensen
1852581c71SMarkus Armbruster #ifndef HW_NVME_NVME_H
1952581c71SMarkus Armbruster #define HW_NVME_NVME_H
2088eea45cSKlaus Jensen
2188eea45cSKlaus Jensen #include "qemu/uuid.h"
22edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h"
2388eea45cSKlaus Jensen #include "hw/block/block.h"
2488eea45cSKlaus Jensen
2588eea45cSKlaus Jensen #include "block/nvme.h"
2688eea45cSKlaus Jensen
2744c2c094SLukasz Maniak #define NVME_MAX_CONTROLLERS 256
2888eea45cSKlaus Jensen #define NVME_MAX_NAMESPACES 256
293276dde4SHeinrich Schuchardt #define NVME_EUI64_DEFAULT ((uint64_t)0x5254000000000000)
3073064edfSJesper Devantier #define NVME_FDP_MAX_EVENTS 63
3173064edfSJesper Devantier #define NVME_FDP_MAXPIDS 128
3288eea45cSKlaus Jensen
336a33f2e9SKlaus Jensen /*
346a33f2e9SKlaus Jensen * The controller only supports Submission and Completion Queue Entry Sizes of
356a33f2e9SKlaus Jensen * 64 and 16 bytes respectively.
366a33f2e9SKlaus Jensen */
376a33f2e9SKlaus Jensen #define NVME_SQES 6
386a33f2e9SKlaus Jensen #define NVME_CQES 4
396a33f2e9SKlaus Jensen
4038f4ac65SKlaus Jensen QEMU_BUILD_BUG_ON(NVME_MAX_NAMESPACES > NVME_NSID_BROADCAST - 1);
4138f4ac65SKlaus Jensen
4288eea45cSKlaus Jensen typedef struct NvmeCtrl NvmeCtrl;
4388eea45cSKlaus Jensen typedef struct NvmeNamespace NvmeNamespace;
4488eea45cSKlaus Jensen
455ffbaeedSKlaus Jensen #define TYPE_NVME_BUS "nvme-bus"
465ffbaeedSKlaus Jensen OBJECT_DECLARE_SIMPLE_TYPE(NvmeBus, NVME_BUS)
475ffbaeedSKlaus Jensen
485ffbaeedSKlaus Jensen typedef struct NvmeBus {
495ffbaeedSKlaus Jensen BusState parent_bus;
505ffbaeedSKlaus Jensen } NvmeBus;
515ffbaeedSKlaus Jensen
5288eea45cSKlaus Jensen #define TYPE_NVME_SUBSYS "nvme-subsys"
5388eea45cSKlaus Jensen #define NVME_SUBSYS(obj) \
5488eea45cSKlaus Jensen OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS)
5599f48ae7SLukasz Maniak #define SUBSYS_SLOT_RSVD (void *)0xFFFF
5688eea45cSKlaus Jensen
5773064edfSJesper Devantier typedef struct NvmeReclaimUnit {
5873064edfSJesper Devantier uint64_t ruamw;
5973064edfSJesper Devantier } NvmeReclaimUnit;
6073064edfSJesper Devantier
6173064edfSJesper Devantier typedef struct NvmeRuHandle {
6273064edfSJesper Devantier uint8_t ruht;
6373064edfSJesper Devantier uint8_t ruha;
6473064edfSJesper Devantier uint64_t event_filter;
6573064edfSJesper Devantier uint8_t lbafi;
6673064edfSJesper Devantier uint64_t ruamw;
6773064edfSJesper Devantier
6873064edfSJesper Devantier /* reclaim units indexed by reclaim group */
6973064edfSJesper Devantier NvmeReclaimUnit *rus;
7073064edfSJesper Devantier } NvmeRuHandle;
7173064edfSJesper Devantier
7273064edfSJesper Devantier typedef struct NvmeFdpEventBuffer {
7373064edfSJesper Devantier NvmeFdpEvent events[NVME_FDP_MAX_EVENTS];
7473064edfSJesper Devantier unsigned int nelems;
7573064edfSJesper Devantier unsigned int start;
7673064edfSJesper Devantier unsigned int next;
7773064edfSJesper Devantier } NvmeFdpEventBuffer;
7873064edfSJesper Devantier
79771dbc3aSKlaus Jensen typedef struct NvmeEnduranceGroup {
80771dbc3aSKlaus Jensen uint8_t event_conf;
8173064edfSJesper Devantier
8273064edfSJesper Devantier struct {
8373064edfSJesper Devantier NvmeFdpEventBuffer host_events, ctrl_events;
8473064edfSJesper Devantier
8573064edfSJesper Devantier uint16_t nruh;
8673064edfSJesper Devantier uint16_t nrg;
8773064edfSJesper Devantier uint8_t rgif;
8873064edfSJesper Devantier uint64_t runs;
8973064edfSJesper Devantier
9073064edfSJesper Devantier uint64_t hbmw;
9173064edfSJesper Devantier uint64_t mbmw;
9273064edfSJesper Devantier uint64_t mbe;
9373064edfSJesper Devantier
9473064edfSJesper Devantier bool enabled;
9573064edfSJesper Devantier
9673064edfSJesper Devantier NvmeRuHandle *ruhs;
9773064edfSJesper Devantier } fdp;
98771dbc3aSKlaus Jensen } NvmeEnduranceGroup;
99771dbc3aSKlaus Jensen
10088eea45cSKlaus Jensen typedef struct NvmeSubsystem {
10188eea45cSKlaus Jensen DeviceState parent_obj;
1025ffbaeedSKlaus Jensen NvmeBus bus;
10388eea45cSKlaus Jensen uint8_t subnqn[256];
104a859eb9fSKlaus Jensen char *serial;
10588eea45cSKlaus Jensen
10688eea45cSKlaus Jensen NvmeCtrl *ctrls[NVME_MAX_CONTROLLERS];
10788eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1];
10873064edfSJesper Devantier NvmeEnduranceGroup endgrp;
10988eea45cSKlaus Jensen
11088eea45cSKlaus Jensen struct {
11188eea45cSKlaus Jensen char *nqn;
11273064edfSJesper Devantier
11373064edfSJesper Devantier struct {
11473064edfSJesper Devantier bool enabled;
11573064edfSJesper Devantier uint64_t runs;
11673064edfSJesper Devantier uint16_t nruh;
11773064edfSJesper Devantier uint32_t nrg;
11873064edfSJesper Devantier } fdp;
11988eea45cSKlaus Jensen } params;
12088eea45cSKlaus Jensen } NvmeSubsystem;
12188eea45cSKlaus Jensen
12288eea45cSKlaus Jensen int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp);
123b0fde9e8SKlaus Jensen void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n);
12488eea45cSKlaus Jensen
nvme_subsys_ctrl(NvmeSubsystem * subsys,uint32_t cntlid)12588eea45cSKlaus Jensen static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys,
12688eea45cSKlaus Jensen uint32_t cntlid)
12788eea45cSKlaus Jensen {
12888eea45cSKlaus Jensen if (!subsys || cntlid >= NVME_MAX_CONTROLLERS) {
12988eea45cSKlaus Jensen return NULL;
13088eea45cSKlaus Jensen }
13188eea45cSKlaus Jensen
13299f48ae7SLukasz Maniak if (subsys->ctrls[cntlid] == SUBSYS_SLOT_RSVD) {
13399f48ae7SLukasz Maniak return NULL;
13499f48ae7SLukasz Maniak }
13599f48ae7SLukasz Maniak
13688eea45cSKlaus Jensen return subsys->ctrls[cntlid];
13788eea45cSKlaus Jensen }
13888eea45cSKlaus Jensen
nvme_subsys_ns(NvmeSubsystem * subsys,uint32_t nsid)13988eea45cSKlaus Jensen static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
14088eea45cSKlaus Jensen uint32_t nsid)
14188eea45cSKlaus Jensen {
14288eea45cSKlaus Jensen if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) {
14388eea45cSKlaus Jensen return NULL;
14488eea45cSKlaus Jensen }
14588eea45cSKlaus Jensen
14688eea45cSKlaus Jensen return subsys->namespaces[nsid];
14788eea45cSKlaus Jensen }
14888eea45cSKlaus Jensen
14988eea45cSKlaus Jensen #define TYPE_NVME_NS "nvme-ns"
15088eea45cSKlaus Jensen #define NVME_NS(obj) \
15188eea45cSKlaus Jensen OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
15288eea45cSKlaus Jensen
15388eea45cSKlaus Jensen typedef struct NvmeZone {
15488eea45cSKlaus Jensen NvmeZoneDescr d;
15588eea45cSKlaus Jensen uint64_t w_ptr;
15688eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeZone) entry;
15788eea45cSKlaus Jensen } NvmeZone;
15888eea45cSKlaus Jensen
15973064edfSJesper Devantier #define FDP_EVT_MAX 0xff
16073064edfSJesper Devantier #define NVME_FDP_MAX_NS_RUHS 32u
16173064edfSJesper Devantier #define FDPVSS 0
16273064edfSJesper Devantier
16373064edfSJesper Devantier static const uint8_t nvme_fdp_evf_shifts[FDP_EVT_MAX] = {
16473064edfSJesper Devantier /* Host events */
16573064edfSJesper Devantier [FDP_EVT_RU_NOT_FULLY_WRITTEN] = 0,
16673064edfSJesper Devantier [FDP_EVT_RU_ATL_EXCEEDED] = 1,
16773064edfSJesper Devantier [FDP_EVT_CTRL_RESET_RUH] = 2,
16873064edfSJesper Devantier [FDP_EVT_INVALID_PID] = 3,
16973064edfSJesper Devantier /* CTRL events */
17073064edfSJesper Devantier [FDP_EVT_MEDIA_REALLOC] = 32,
17173064edfSJesper Devantier [FDP_EVT_RUH_IMPLICIT_RU_CHANGE] = 33,
17273064edfSJesper Devantier };
17373064edfSJesper Devantier
174bdc31646SRoque Arcudia Hernandez #define NGUID_LEN 16
175bdc31646SRoque Arcudia Hernandez
176bdc31646SRoque Arcudia Hernandez typedef struct {
177bdc31646SRoque Arcudia Hernandez uint8_t data[NGUID_LEN];
178bdc31646SRoque Arcudia Hernandez } NvmeNGUID;
179bdc31646SRoque Arcudia Hernandez
180bdc31646SRoque Arcudia Hernandez bool nvme_nguid_is_null(const NvmeNGUID *nguid);
181bdc31646SRoque Arcudia Hernandez
182bdc31646SRoque Arcudia Hernandez extern const PropertyInfo qdev_prop_nguid;
183bdc31646SRoque Arcudia Hernandez
184bdc31646SRoque Arcudia Hernandez #define DEFINE_PROP_NGUID_NODEFAULT(_name, _state, _field) \
185bdc31646SRoque Arcudia Hernandez DEFINE_PROP(_name, _state, _field, qdev_prop_nguid, NvmeNGUID)
186bdc31646SRoque Arcudia Hernandez
18788eea45cSKlaus Jensen typedef struct NvmeNamespaceParams {
18888eea45cSKlaus Jensen bool detached;
18988eea45cSKlaus Jensen bool shared;
19088eea45cSKlaus Jensen uint32_t nsid;
19188eea45cSKlaus Jensen QemuUUID uuid;
192bdc31646SRoque Arcudia Hernandez NvmeNGUID nguid;
1936870cfb8SHeinrich Schuchardt uint64_t eui64;
1943276dde4SHeinrich Schuchardt bool eui64_default;
19588eea45cSKlaus Jensen
19688eea45cSKlaus Jensen uint16_t ms;
19788eea45cSKlaus Jensen uint8_t mset;
19888eea45cSKlaus Jensen uint8_t pi;
19988eea45cSKlaus Jensen uint8_t pil;
20044219b60SNaveen Nagar uint8_t pif;
20188eea45cSKlaus Jensen
20288eea45cSKlaus Jensen uint16_t mssrl;
20388eea45cSKlaus Jensen uint32_t mcl;
20488eea45cSKlaus Jensen uint8_t msrc;
20588eea45cSKlaus Jensen
20688eea45cSKlaus Jensen bool zoned;
20788eea45cSKlaus Jensen bool cross_zone_read;
20888eea45cSKlaus Jensen uint64_t zone_size_bs;
20988eea45cSKlaus Jensen uint64_t zone_cap_bs;
21088eea45cSKlaus Jensen uint32_t max_active_zones;
21188eea45cSKlaus Jensen uint32_t max_open_zones;
21288eea45cSKlaus Jensen uint32_t zd_extension_size;
213e321b4cdSKlaus Jensen
214e321b4cdSKlaus Jensen uint32_t numzrwa;
215e321b4cdSKlaus Jensen uint64_t zrwas;
216e321b4cdSKlaus Jensen uint64_t zrwafg;
21773064edfSJesper Devantier
21873064edfSJesper Devantier struct {
21973064edfSJesper Devantier char *ruhs;
22073064edfSJesper Devantier } fdp;
22188eea45cSKlaus Jensen } NvmeNamespaceParams;
22288eea45cSKlaus Jensen
223ebd1568fSAlan Adamson typedef struct NvmeAtomic {
224ebd1568fSAlan Adamson uint32_t atomic_max_write_size;
225ebd1568fSAlan Adamson bool atomic_writes;
226ebd1568fSAlan Adamson } NvmeAtomic;
227ebd1568fSAlan Adamson
22888eea45cSKlaus Jensen typedef struct NvmeNamespace {
22988eea45cSKlaus Jensen DeviceState parent_obj;
23088eea45cSKlaus Jensen BlockConf blkconf;
23188eea45cSKlaus Jensen int32_t bootindex;
23288eea45cSKlaus Jensen int64_t size;
23388eea45cSKlaus Jensen int64_t moff;
23488eea45cSKlaus Jensen NvmeIdNs id_ns;
23544219b60SNaveen Nagar NvmeIdNsNvm id_ns_nvm;
236*79e49005SArun Kumar NvmeIdNsInd id_ns_ind;
23788eea45cSKlaus Jensen NvmeLBAF lbaf;
238763c05dfSNaveen Nagar unsigned int nlbaf;
23988eea45cSKlaus Jensen size_t lbasz;
24088eea45cSKlaus Jensen const uint32_t *iocs;
24188eea45cSKlaus Jensen uint8_t csi;
24288eea45cSKlaus Jensen uint16_t status;
24388eea45cSKlaus Jensen int attached;
24444219b60SNaveen Nagar uint8_t pif;
24588eea45cSKlaus Jensen
246e321b4cdSKlaus Jensen struct {
247e321b4cdSKlaus Jensen uint16_t zrwas;
248e321b4cdSKlaus Jensen uint16_t zrwafg;
249e321b4cdSKlaus Jensen uint32_t numzrwa;
250e321b4cdSKlaus Jensen } zns;
251e321b4cdSKlaus Jensen
25288eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeNamespace) entry;
25388eea45cSKlaus Jensen
25488eea45cSKlaus Jensen NvmeIdNsZoned *id_ns_zoned;
25588eea45cSKlaus Jensen NvmeZone *zone_array;
25688eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) exp_open_zones;
25788eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) imp_open_zones;
25888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) closed_zones;
25988eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeZone) full_zones;
26088eea45cSKlaus Jensen uint32_t num_zones;
26188eea45cSKlaus Jensen uint64_t zone_size;
26288eea45cSKlaus Jensen uint64_t zone_capacity;
26388eea45cSKlaus Jensen uint32_t zone_size_log2;
26488eea45cSKlaus Jensen uint8_t *zd_extensions;
26588eea45cSKlaus Jensen int32_t nr_open_zones;
26688eea45cSKlaus Jensen int32_t nr_active_zones;
26788eea45cSKlaus Jensen
26888eea45cSKlaus Jensen NvmeNamespaceParams params;
269534a93d3SNiklas Cassel NvmeSubsystem *subsys;
27073064edfSJesper Devantier NvmeEnduranceGroup *endgrp;
27188eea45cSKlaus Jensen
27288eea45cSKlaus Jensen struct {
27388eea45cSKlaus Jensen uint32_t err_rec;
27488eea45cSKlaus Jensen } features;
27573064edfSJesper Devantier
27673064edfSJesper Devantier struct {
27773064edfSJesper Devantier uint16_t nphs;
27873064edfSJesper Devantier /* reclaim unit handle identifiers indexed by placement handle */
27973064edfSJesper Devantier uint16_t *phs;
28073064edfSJesper Devantier } fdp;
28188eea45cSKlaus Jensen } NvmeNamespace;
28288eea45cSKlaus Jensen
nvme_nsid(NvmeNamespace * ns)28388eea45cSKlaus Jensen static inline uint32_t nvme_nsid(NvmeNamespace *ns)
28488eea45cSKlaus Jensen {
28588eea45cSKlaus Jensen if (ns) {
28688eea45cSKlaus Jensen return ns->params.nsid;
28788eea45cSKlaus Jensen }
28888eea45cSKlaus Jensen
28988eea45cSKlaus Jensen return 0;
29088eea45cSKlaus Jensen }
29188eea45cSKlaus Jensen
nvme_l2b(NvmeNamespace * ns,uint64_t lba)29288eea45cSKlaus Jensen static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba)
29388eea45cSKlaus Jensen {
29488eea45cSKlaus Jensen return lba << ns->lbaf.ds;
29588eea45cSKlaus Jensen }
29688eea45cSKlaus Jensen
nvme_m2b(NvmeNamespace * ns,uint64_t lba)29788eea45cSKlaus Jensen static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba)
29888eea45cSKlaus Jensen {
29988eea45cSKlaus Jensen return ns->lbaf.ms * lba;
30088eea45cSKlaus Jensen }
30188eea45cSKlaus Jensen
nvme_moff(NvmeNamespace * ns,uint64_t lba)30288eea45cSKlaus Jensen static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba)
30388eea45cSKlaus Jensen {
30488eea45cSKlaus Jensen return ns->moff + nvme_m2b(ns, lba);
30588eea45cSKlaus Jensen }
30688eea45cSKlaus Jensen
nvme_ns_ext(NvmeNamespace * ns)30788eea45cSKlaus Jensen static inline bool nvme_ns_ext(NvmeNamespace *ns)
30888eea45cSKlaus Jensen {
30988eea45cSKlaus Jensen return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas);
31088eea45cSKlaus Jensen }
31188eea45cSKlaus Jensen
nvme_get_zone_state(NvmeZone * zone)31288eea45cSKlaus Jensen static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone)
31388eea45cSKlaus Jensen {
31488eea45cSKlaus Jensen return zone->d.zs >> 4;
31588eea45cSKlaus Jensen }
31688eea45cSKlaus Jensen
nvme_set_zone_state(NvmeZone * zone,NvmeZoneState state)31788eea45cSKlaus Jensen static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state)
31888eea45cSKlaus Jensen {
31988eea45cSKlaus Jensen zone->d.zs = state << 4;
32088eea45cSKlaus Jensen }
32188eea45cSKlaus Jensen
nvme_zone_rd_boundary(NvmeNamespace * ns,NvmeZone * zone)32288eea45cSKlaus Jensen static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone)
32388eea45cSKlaus Jensen {
32488eea45cSKlaus Jensen return zone->d.zslba + ns->zone_size;
32588eea45cSKlaus Jensen }
32688eea45cSKlaus Jensen
nvme_zone_wr_boundary(NvmeZone * zone)32788eea45cSKlaus Jensen static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone)
32888eea45cSKlaus Jensen {
32988eea45cSKlaus Jensen return zone->d.zslba + zone->d.zcap;
33088eea45cSKlaus Jensen }
33188eea45cSKlaus Jensen
nvme_wp_is_valid(NvmeZone * zone)33288eea45cSKlaus Jensen static inline bool nvme_wp_is_valid(NvmeZone *zone)
33388eea45cSKlaus Jensen {
33488eea45cSKlaus Jensen uint8_t st = nvme_get_zone_state(zone);
33588eea45cSKlaus Jensen
33688eea45cSKlaus Jensen return st != NVME_ZONE_STATE_FULL &&
33788eea45cSKlaus Jensen st != NVME_ZONE_STATE_READ_ONLY &&
33888eea45cSKlaus Jensen st != NVME_ZONE_STATE_OFFLINE;
33988eea45cSKlaus Jensen }
34088eea45cSKlaus Jensen
nvme_get_zd_extension(NvmeNamespace * ns,uint32_t zone_idx)34188eea45cSKlaus Jensen static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns,
34288eea45cSKlaus Jensen uint32_t zone_idx)
34388eea45cSKlaus Jensen {
34488eea45cSKlaus Jensen return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size];
34588eea45cSKlaus Jensen }
34688eea45cSKlaus Jensen
nvme_aor_inc_open(NvmeNamespace * ns)34788eea45cSKlaus Jensen static inline void nvme_aor_inc_open(NvmeNamespace *ns)
34888eea45cSKlaus Jensen {
34988eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0);
35088eea45cSKlaus Jensen if (ns->params.max_open_zones) {
35188eea45cSKlaus Jensen ns->nr_open_zones++;
35288eea45cSKlaus Jensen assert(ns->nr_open_zones <= ns->params.max_open_zones);
35388eea45cSKlaus Jensen }
35488eea45cSKlaus Jensen }
35588eea45cSKlaus Jensen
nvme_aor_dec_open(NvmeNamespace * ns)35688eea45cSKlaus Jensen static inline void nvme_aor_dec_open(NvmeNamespace *ns)
35788eea45cSKlaus Jensen {
35888eea45cSKlaus Jensen if (ns->params.max_open_zones) {
35988eea45cSKlaus Jensen assert(ns->nr_open_zones > 0);
36088eea45cSKlaus Jensen ns->nr_open_zones--;
36188eea45cSKlaus Jensen }
36288eea45cSKlaus Jensen assert(ns->nr_open_zones >= 0);
36388eea45cSKlaus Jensen }
36488eea45cSKlaus Jensen
nvme_aor_inc_active(NvmeNamespace * ns)36588eea45cSKlaus Jensen static inline void nvme_aor_inc_active(NvmeNamespace *ns)
36688eea45cSKlaus Jensen {
36788eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0);
36888eea45cSKlaus Jensen if (ns->params.max_active_zones) {
36988eea45cSKlaus Jensen ns->nr_active_zones++;
37088eea45cSKlaus Jensen assert(ns->nr_active_zones <= ns->params.max_active_zones);
37188eea45cSKlaus Jensen }
37288eea45cSKlaus Jensen }
37388eea45cSKlaus Jensen
nvme_aor_dec_active(NvmeNamespace * ns)37488eea45cSKlaus Jensen static inline void nvme_aor_dec_active(NvmeNamespace *ns)
37588eea45cSKlaus Jensen {
37688eea45cSKlaus Jensen if (ns->params.max_active_zones) {
37788eea45cSKlaus Jensen assert(ns->nr_active_zones > 0);
37888eea45cSKlaus Jensen ns->nr_active_zones--;
37988eea45cSKlaus Jensen assert(ns->nr_active_zones >= ns->nr_open_zones);
38088eea45cSKlaus Jensen }
38188eea45cSKlaus Jensen assert(ns->nr_active_zones >= 0);
38288eea45cSKlaus Jensen }
38388eea45cSKlaus Jensen
nvme_fdp_stat_inc(uint64_t * a,uint64_t b)38473064edfSJesper Devantier static inline void nvme_fdp_stat_inc(uint64_t *a, uint64_t b)
38573064edfSJesper Devantier {
38673064edfSJesper Devantier uint64_t ret = *a + b;
38773064edfSJesper Devantier *a = ret < *a ? UINT64_MAX : ret;
38873064edfSJesper Devantier }
38973064edfSJesper Devantier
39088eea45cSKlaus Jensen void nvme_ns_init_format(NvmeNamespace *ns);
3915e4f6bccSKlaus Jensen int nvme_ns_setup(NvmeNamespace *ns, Error **errp);
39288eea45cSKlaus Jensen void nvme_ns_drain(NvmeNamespace *ns);
39388eea45cSKlaus Jensen void nvme_ns_shutdown(NvmeNamespace *ns);
39488eea45cSKlaus Jensen void nvme_ns_cleanup(NvmeNamespace *ns);
39588eea45cSKlaus Jensen
39688eea45cSKlaus Jensen typedef struct NvmeAsyncEvent {
39788eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeAsyncEvent) entry;
39888eea45cSKlaus Jensen NvmeAerResult result;
39988eea45cSKlaus Jensen } NvmeAsyncEvent;
40088eea45cSKlaus Jensen
40188eea45cSKlaus Jensen enum {
40288eea45cSKlaus Jensen NVME_SG_ALLOC = 1 << 0,
40388eea45cSKlaus Jensen NVME_SG_DMA = 1 << 1,
40488eea45cSKlaus Jensen };
40588eea45cSKlaus Jensen
40688eea45cSKlaus Jensen typedef struct NvmeSg {
40788eea45cSKlaus Jensen int flags;
40888eea45cSKlaus Jensen
40988eea45cSKlaus Jensen union {
41088eea45cSKlaus Jensen QEMUSGList qsg;
41188eea45cSKlaus Jensen QEMUIOVector iov;
41288eea45cSKlaus Jensen };
41388eea45cSKlaus Jensen } NvmeSg;
41488eea45cSKlaus Jensen
41588eea45cSKlaus Jensen typedef enum NvmeTxDirection {
41688eea45cSKlaus Jensen NVME_TX_DIRECTION_TO_DEVICE = 0,
41788eea45cSKlaus Jensen NVME_TX_DIRECTION_FROM_DEVICE = 1,
41888eea45cSKlaus Jensen } NvmeTxDirection;
41988eea45cSKlaus Jensen
42088eea45cSKlaus Jensen typedef struct NvmeRequest {
42188eea45cSKlaus Jensen struct NvmeSQueue *sq;
42288eea45cSKlaus Jensen struct NvmeNamespace *ns;
42388eea45cSKlaus Jensen BlockAIOCB *aiocb;
42488eea45cSKlaus Jensen uint16_t status;
42588eea45cSKlaus Jensen void *opaque;
42688eea45cSKlaus Jensen NvmeCqe cqe;
42788eea45cSKlaus Jensen NvmeCmd cmd;
42888eea45cSKlaus Jensen BlockAcctCookie acct;
42988eea45cSKlaus Jensen NvmeSg sg;
430ebd1568fSAlan Adamson bool atomic_write;
43188eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeRequest)entry;
43288eea45cSKlaus Jensen } NvmeRequest;
43388eea45cSKlaus Jensen
43488eea45cSKlaus Jensen typedef struct NvmeBounceContext {
43588eea45cSKlaus Jensen NvmeRequest *req;
43688eea45cSKlaus Jensen
43788eea45cSKlaus Jensen struct {
43888eea45cSKlaus Jensen QEMUIOVector iov;
43988eea45cSKlaus Jensen uint8_t *bounce;
44088eea45cSKlaus Jensen } data, mdata;
44188eea45cSKlaus Jensen } NvmeBounceContext;
44288eea45cSKlaus Jensen
nvme_adm_opc_str(uint8_t opc)44388eea45cSKlaus Jensen static inline const char *nvme_adm_opc_str(uint8_t opc)
44488eea45cSKlaus Jensen {
44588eea45cSKlaus Jensen switch (opc) {
44688eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_SQ: return "NVME_ADM_CMD_DELETE_SQ";
44788eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_SQ: return "NVME_ADM_CMD_CREATE_SQ";
44888eea45cSKlaus Jensen case NVME_ADM_CMD_GET_LOG_PAGE: return "NVME_ADM_CMD_GET_LOG_PAGE";
44988eea45cSKlaus Jensen case NVME_ADM_CMD_DELETE_CQ: return "NVME_ADM_CMD_DELETE_CQ";
45088eea45cSKlaus Jensen case NVME_ADM_CMD_CREATE_CQ: return "NVME_ADM_CMD_CREATE_CQ";
45188eea45cSKlaus Jensen case NVME_ADM_CMD_IDENTIFY: return "NVME_ADM_CMD_IDENTIFY";
45288eea45cSKlaus Jensen case NVME_ADM_CMD_ABORT: return "NVME_ADM_CMD_ABORT";
45388eea45cSKlaus Jensen case NVME_ADM_CMD_SET_FEATURES: return "NVME_ADM_CMD_SET_FEATURES";
45488eea45cSKlaus Jensen case NVME_ADM_CMD_GET_FEATURES: return "NVME_ADM_CMD_GET_FEATURES";
45588eea45cSKlaus Jensen case NVME_ADM_CMD_ASYNC_EV_REQ: return "NVME_ADM_CMD_ASYNC_EV_REQ";
45688eea45cSKlaus Jensen case NVME_ADM_CMD_NS_ATTACHMENT: return "NVME_ADM_CMD_NS_ATTACHMENT";
457e181d3daSGollu Appalanaidu case NVME_ADM_CMD_DIRECTIVE_SEND: return "NVME_ADM_CMD_DIRECTIVE_SEND";
45811871f53SŁukasz Gieryk case NVME_ADM_CMD_VIRT_MNGMT: return "NVME_ADM_CMD_VIRT_MNGMT";
459e181d3daSGollu Appalanaidu case NVME_ADM_CMD_DIRECTIVE_RECV: return "NVME_ADM_CMD_DIRECTIVE_RECV";
4603f7fe8deSJinhao Fan case NVME_ADM_CMD_DBBUF_CONFIG: return "NVME_ADM_CMD_DBBUF_CONFIG";
46188eea45cSKlaus Jensen case NVME_ADM_CMD_FORMAT_NVM: return "NVME_ADM_CMD_FORMAT_NVM";
46288eea45cSKlaus Jensen default: return "NVME_ADM_CMD_UNKNOWN";
46388eea45cSKlaus Jensen }
46488eea45cSKlaus Jensen }
46588eea45cSKlaus Jensen
nvme_io_opc_str(uint8_t opc)46688eea45cSKlaus Jensen static inline const char *nvme_io_opc_str(uint8_t opc)
46788eea45cSKlaus Jensen {
46888eea45cSKlaus Jensen switch (opc) {
46988eea45cSKlaus Jensen case NVME_CMD_FLUSH: return "NVME_NVM_CMD_FLUSH";
47088eea45cSKlaus Jensen case NVME_CMD_WRITE: return "NVME_NVM_CMD_WRITE";
47188eea45cSKlaus Jensen case NVME_CMD_READ: return "NVME_NVM_CMD_READ";
47288eea45cSKlaus Jensen case NVME_CMD_COMPARE: return "NVME_NVM_CMD_COMPARE";
47388eea45cSKlaus Jensen case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES";
47488eea45cSKlaus Jensen case NVME_CMD_DSM: return "NVME_NVM_CMD_DSM";
47588eea45cSKlaus Jensen case NVME_CMD_VERIFY: return "NVME_NVM_CMD_VERIFY";
47688eea45cSKlaus Jensen case NVME_CMD_COPY: return "NVME_NVM_CMD_COPY";
47788eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_SEND: return "NVME_ZONED_CMD_MGMT_SEND";
47888eea45cSKlaus Jensen case NVME_CMD_ZONE_MGMT_RECV: return "NVME_ZONED_CMD_MGMT_RECV";
47988eea45cSKlaus Jensen case NVME_CMD_ZONE_APPEND: return "NVME_ZONED_CMD_ZONE_APPEND";
48088eea45cSKlaus Jensen default: return "NVME_NVM_CMD_UNKNOWN";
48188eea45cSKlaus Jensen }
48288eea45cSKlaus Jensen }
48388eea45cSKlaus Jensen
48488eea45cSKlaus Jensen typedef struct NvmeSQueue {
48588eea45cSKlaus Jensen struct NvmeCtrl *ctrl;
48688eea45cSKlaus Jensen uint16_t sqid;
48788eea45cSKlaus Jensen uint16_t cqid;
48888eea45cSKlaus Jensen uint32_t head;
48988eea45cSKlaus Jensen uint32_t tail;
49088eea45cSKlaus Jensen uint32_t size;
49188eea45cSKlaus Jensen uint64_t dma_addr;
4923f7fe8deSJinhao Fan uint64_t db_addr;
4933f7fe8deSJinhao Fan uint64_t ei_addr;
494d38cc6fdSKlaus Jensen QEMUBH *bh;
4952e53b0b4SJinhao Fan EventNotifier notifier;
4962e53b0b4SJinhao Fan bool ioeventfd_enabled;
49788eea45cSKlaus Jensen NvmeRequest *io_req;
49888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list;
49988eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) out_req_list;
50088eea45cSKlaus Jensen QTAILQ_ENTRY(NvmeSQueue) entry;
50188eea45cSKlaus Jensen } NvmeSQueue;
50288eea45cSKlaus Jensen
50388eea45cSKlaus Jensen typedef struct NvmeCQueue {
50488eea45cSKlaus Jensen struct NvmeCtrl *ctrl;
50588eea45cSKlaus Jensen uint8_t phase;
50688eea45cSKlaus Jensen uint16_t cqid;
50788eea45cSKlaus Jensen uint16_t irq_enabled;
50888eea45cSKlaus Jensen uint32_t head;
50988eea45cSKlaus Jensen uint32_t tail;
51088eea45cSKlaus Jensen uint32_t vector;
51188eea45cSKlaus Jensen uint32_t size;
51288eea45cSKlaus Jensen uint64_t dma_addr;
5133f7fe8deSJinhao Fan uint64_t db_addr;
5143f7fe8deSJinhao Fan uint64_t ei_addr;
515d38cc6fdSKlaus Jensen QEMUBH *bh;
5162e53b0b4SJinhao Fan EventNotifier notifier;
5172e53b0b4SJinhao Fan bool ioeventfd_enabled;
51888eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeSQueue) sq_list;
51988eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeRequest) req_list;
52088eea45cSKlaus Jensen } NvmeCQueue;
52188eea45cSKlaus Jensen
52288eea45cSKlaus Jensen #define TYPE_NVME "nvme"
52388eea45cSKlaus Jensen #define NVME(obj) \
52488eea45cSKlaus Jensen OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME)
52588eea45cSKlaus Jensen
52688eea45cSKlaus Jensen typedef struct NvmeParams {
52788eea45cSKlaus Jensen char *serial;
52888eea45cSKlaus Jensen uint32_t num_queues; /* deprecated since 5.1 */
52988eea45cSKlaus Jensen uint32_t max_ioqpairs;
53088eea45cSKlaus Jensen uint16_t msix_qsize;
531bc432bc5SJohn Berg uint16_t mqes;
53288eea45cSKlaus Jensen uint32_t cmb_size_mb;
53388eea45cSKlaus Jensen uint8_t aerl;
53488eea45cSKlaus Jensen uint32_t aer_max_queued;
53588eea45cSKlaus Jensen uint8_t mdts;
53688eea45cSKlaus Jensen uint8_t vsl;
53788eea45cSKlaus Jensen bool use_intel_id;
53888eea45cSKlaus Jensen uint8_t zasl;
539cccc2651SNiklas Cassel bool auto_transition_zones;
54088eea45cSKlaus Jensen bool legacy_cmb;
5412e53b0b4SJinhao Fan bool ioeventfd;
542c6159d0eSMinwoo Im uint16_t sriov_max_vfs;
543746d42b1SŁukasz Gieryk uint16_t sriov_vq_flexible;
544746d42b1SŁukasz Gieryk uint16_t sriov_vi_flexible;
54515ef124cSMinwoo Im uint32_t sriov_max_vq_per_vf;
54615ef124cSMinwoo Im uint32_t sriov_max_vi_per_vf;
547fa905f65SKlaus Jensen bool msix_exclusive_bar;
548e4bcb586SKlaus Jensen
549e4bcb586SKlaus Jensen struct {
550e4bcb586SKlaus Jensen bool mem;
551e4bcb586SKlaus Jensen } ctratt;
552ebd1568fSAlan Adamson
553ebd1568fSAlan Adamson uint16_t atomic_awun;
554ebd1568fSAlan Adamson uint16_t atomic_awupf;
555ebd1568fSAlan Adamson bool atomic_dn;
55688eea45cSKlaus Jensen } NvmeParams;
55788eea45cSKlaus Jensen
55888eea45cSKlaus Jensen typedef struct NvmeCtrl {
55988eea45cSKlaus Jensen PCIDevice parent_obj;
56088eea45cSKlaus Jensen MemoryRegion bar0;
56188eea45cSKlaus Jensen MemoryRegion iomem;
56288eea45cSKlaus Jensen NvmeBar bar;
56388eea45cSKlaus Jensen NvmeParams params;
56488eea45cSKlaus Jensen NvmeBus bus;
56588eea45cSKlaus Jensen
56688eea45cSKlaus Jensen uint16_t cntlid;
56788eea45cSKlaus Jensen bool qs_created;
56888eea45cSKlaus Jensen uint32_t page_size;
56988eea45cSKlaus Jensen uint16_t page_bits;
57088eea45cSKlaus Jensen uint16_t max_prp_ents;
57188eea45cSKlaus Jensen uint32_t max_q_ents;
57288eea45cSKlaus Jensen uint8_t outstanding_aers;
57388eea45cSKlaus Jensen uint32_t irq_status;
57483d7ed5cSKlaus Jensen int cq_pending;
57588eea45cSKlaus Jensen uint64_t host_timestamp; /* Timestamp sent by the host */
57688eea45cSKlaus Jensen uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
57788eea45cSKlaus Jensen uint64_t starttime_ms;
57888eea45cSKlaus Jensen uint16_t temperature;
57988eea45cSKlaus Jensen uint8_t smart_critical_warning;
580decc0261SŁukasz Gieryk uint32_t conf_msix_qsize;
581decc0261SŁukasz Gieryk uint32_t conf_ioqpairs;
5823f7fe8deSJinhao Fan uint64_t dbbuf_dbs;
5833f7fe8deSJinhao Fan uint64_t dbbuf_eis;
5843f7fe8deSJinhao Fan bool dbbuf_enabled;
58588eea45cSKlaus Jensen
58688eea45cSKlaus Jensen struct {
58788eea45cSKlaus Jensen MemoryRegion mem;
58888eea45cSKlaus Jensen uint8_t *buf;
58988eea45cSKlaus Jensen bool cmse;
59088eea45cSKlaus Jensen hwaddr cba;
59188eea45cSKlaus Jensen } cmb;
59288eea45cSKlaus Jensen
59388eea45cSKlaus Jensen struct {
59488eea45cSKlaus Jensen HostMemoryBackend *dev;
59588eea45cSKlaus Jensen bool cmse;
59688eea45cSKlaus Jensen hwaddr cba;
59788eea45cSKlaus Jensen } pmr;
59888eea45cSKlaus Jensen
59988eea45cSKlaus Jensen uint8_t aer_mask;
60088eea45cSKlaus Jensen NvmeRequest **aer_reqs;
60188eea45cSKlaus Jensen QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue;
60288eea45cSKlaus Jensen int aer_queued;
60388eea45cSKlaus Jensen
60488eea45cSKlaus Jensen uint32_t dmrsl;
60588eea45cSKlaus Jensen
60688eea45cSKlaus Jensen /* Namespace ID is started with 1 so bitmap should be 1-based */
60788eea45cSKlaus Jensen #define NVME_CHANGED_NSID_SIZE (NVME_MAX_NAMESPACES + 1)
60888eea45cSKlaus Jensen DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE);
60988eea45cSKlaus Jensen
61088eea45cSKlaus Jensen NvmeSubsystem *subsys;
61188eea45cSKlaus Jensen
61288eea45cSKlaus Jensen NvmeNamespace namespace;
61388eea45cSKlaus Jensen NvmeNamespace *namespaces[NVME_MAX_NAMESPACES + 1];
61488eea45cSKlaus Jensen NvmeSQueue **sq;
61588eea45cSKlaus Jensen NvmeCQueue **cq;
61688eea45cSKlaus Jensen NvmeSQueue admin_sq;
61788eea45cSKlaus Jensen NvmeCQueue admin_cq;
61888eea45cSKlaus Jensen NvmeIdCtrl id_ctrl;
61988eea45cSKlaus Jensen
62088eea45cSKlaus Jensen struct {
62188eea45cSKlaus Jensen struct {
62288eea45cSKlaus Jensen uint16_t temp_thresh_hi;
62388eea45cSKlaus Jensen uint16_t temp_thresh_low;
62488eea45cSKlaus Jensen };
625d0c0697bSNaveen Nagar
62688eea45cSKlaus Jensen uint32_t async_config;
627d0c0697bSNaveen Nagar NvmeHostBehaviorSupport hbs;
62888eea45cSKlaus Jensen } features;
6295e6f963fSLukasz Maniak
6305e6f963fSLukasz Maniak NvmePriCtrlCap pri_ctrl_cap;
6311a494d11SMinwoo Im uint32_t nr_sec_ctrls;
632c6159d0eSMinwoo Im NvmeSecCtrlEntry *sec_ctrl_list;
63311871f53SŁukasz Gieryk struct {
63411871f53SŁukasz Gieryk uint16_t vqrfap;
63511871f53SŁukasz Gieryk uint16_t virfap;
63611871f53SŁukasz Gieryk } next_pri_ctrl_cap; /* These override pri_ctrl_cap after reset */
637ebd1568fSAlan Adamson uint32_t dn; /* Disable Normal */
638ebd1568fSAlan Adamson NvmeAtomic atomic;
63988eea45cSKlaus Jensen } NvmeCtrl;
64088eea45cSKlaus Jensen
6411e9c685eSŁukasz Gieryk typedef enum NvmeResetType {
6421e9c685eSŁukasz Gieryk NVME_RESET_FUNCTION = 0,
6431e9c685eSŁukasz Gieryk NVME_RESET_CONTROLLER = 1,
6441e9c685eSŁukasz Gieryk } NvmeResetType;
6451e9c685eSŁukasz Gieryk
nvme_ns(NvmeCtrl * n,uint32_t nsid)64688eea45cSKlaus Jensen static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
64788eea45cSKlaus Jensen {
64888eea45cSKlaus Jensen if (!nsid || nsid > NVME_MAX_NAMESPACES) {
64988eea45cSKlaus Jensen return NULL;
65088eea45cSKlaus Jensen }
65188eea45cSKlaus Jensen
65288eea45cSKlaus Jensen return n->namespaces[nsid];
65388eea45cSKlaus Jensen }
65488eea45cSKlaus Jensen
nvme_cq(NvmeRequest * req)65588eea45cSKlaus Jensen static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
65688eea45cSKlaus Jensen {
65788eea45cSKlaus Jensen NvmeSQueue *sq = req->sq;
65888eea45cSKlaus Jensen NvmeCtrl *n = sq->ctrl;
65988eea45cSKlaus Jensen
66088eea45cSKlaus Jensen return n->cq[sq->cqid];
66188eea45cSKlaus Jensen }
66288eea45cSKlaus Jensen
nvme_ctrl(NvmeRequest * req)66388eea45cSKlaus Jensen static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req)
66488eea45cSKlaus Jensen {
66588eea45cSKlaus Jensen NvmeSQueue *sq = req->sq;
66688eea45cSKlaus Jensen return sq->ctrl;
66788eea45cSKlaus Jensen }
66888eea45cSKlaus Jensen
nvme_cid(NvmeRequest * req)66988eea45cSKlaus Jensen static inline uint16_t nvme_cid(NvmeRequest *req)
67088eea45cSKlaus Jensen {
67188eea45cSKlaus Jensen if (!req) {
67288eea45cSKlaus Jensen return 0xffff;
67388eea45cSKlaus Jensen }
67488eea45cSKlaus Jensen
67588eea45cSKlaus Jensen return le16_to_cpu(req->cqe.cid);
67688eea45cSKlaus Jensen }
67788eea45cSKlaus Jensen
nvme_sctrl(NvmeCtrl * n)67899f48ae7SLukasz Maniak static inline NvmeSecCtrlEntry *nvme_sctrl(NvmeCtrl *n)
67999f48ae7SLukasz Maniak {
68099f48ae7SLukasz Maniak PCIDevice *pci_dev = &n->parent_obj;
68199f48ae7SLukasz Maniak NvmeCtrl *pf = NVME(pcie_sriov_get_pf(pci_dev));
68299f48ae7SLukasz Maniak
68399f48ae7SLukasz Maniak if (pci_is_vf(pci_dev)) {
6841a494d11SMinwoo Im return &pf->sec_ctrl_list[pcie_sriov_vf_number(pci_dev)];
68599f48ae7SLukasz Maniak }
68699f48ae7SLukasz Maniak
68799f48ae7SLukasz Maniak return NULL;
68899f48ae7SLukasz Maniak }
68999f48ae7SLukasz Maniak
nvme_sctrl_for_cntlid(NvmeCtrl * n,uint16_t cntlid)69011871f53SŁukasz Gieryk static inline NvmeSecCtrlEntry *nvme_sctrl_for_cntlid(NvmeCtrl *n,
69111871f53SŁukasz Gieryk uint16_t cntlid)
69211871f53SŁukasz Gieryk {
6931a494d11SMinwoo Im NvmeSecCtrlEntry *list = n->sec_ctrl_list;
69411871f53SŁukasz Gieryk uint8_t i;
69511871f53SŁukasz Gieryk
6961a494d11SMinwoo Im for (i = 0; i < n->nr_sec_ctrls; i++) {
6971a494d11SMinwoo Im if (le16_to_cpu(list[i].scid) == cntlid) {
6981a494d11SMinwoo Im return &list[i];
69911871f53SŁukasz Gieryk }
70011871f53SŁukasz Gieryk }
70111871f53SŁukasz Gieryk
70211871f53SŁukasz Gieryk return NULL;
70311871f53SŁukasz Gieryk }
70411871f53SŁukasz Gieryk
70588eea45cSKlaus Jensen void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns);
7068d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len,
70788eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req);
7088d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_mdata(NvmeCtrl *n, void *ptr, uint32_t len,
70988eea45cSKlaus Jensen NvmeTxDirection dir, NvmeRequest *req);
71088eea45cSKlaus Jensen void nvme_rw_complete_cb(void *opaque, int ret);
71188eea45cSKlaus Jensen uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len,
71288eea45cSKlaus Jensen NvmeCmd *cmd);
71388eea45cSKlaus Jensen
71452581c71SMarkus Armbruster #endif /* HW_NVME_NVME_H */
715