xref: /openbmc/qemu/hw/nvme/nvme.h (revision 1a494d119abb57e835f1230f4524f1eb67eb83e9)
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
29*1a494d11SMinwoo Im #define NVME_MAX_VFS 127
303276dde4SHeinrich Schuchardt #define NVME_EUI64_DEFAULT ((uint64_t)0x5254000000000000)
3173064edfSJesper Devantier #define NVME_FDP_MAX_EVENTS 63
3273064edfSJesper Devantier #define NVME_FDP_MAXPIDS 128
3388eea45cSKlaus Jensen 
346a33f2e9SKlaus Jensen /*
356a33f2e9SKlaus Jensen  * The controller only supports Submission and Completion Queue Entry Sizes of
366a33f2e9SKlaus Jensen  * 64 and 16 bytes respectively.
376a33f2e9SKlaus Jensen  */
386a33f2e9SKlaus Jensen #define NVME_SQES 6
396a33f2e9SKlaus Jensen #define NVME_CQES 4
406a33f2e9SKlaus Jensen 
4138f4ac65SKlaus Jensen QEMU_BUILD_BUG_ON(NVME_MAX_NAMESPACES > NVME_NSID_BROADCAST - 1);
4238f4ac65SKlaus Jensen 
4388eea45cSKlaus Jensen typedef struct NvmeCtrl NvmeCtrl;
4488eea45cSKlaus Jensen typedef struct NvmeNamespace NvmeNamespace;
4588eea45cSKlaus Jensen 
465ffbaeedSKlaus Jensen #define TYPE_NVME_BUS "nvme-bus"
475ffbaeedSKlaus Jensen OBJECT_DECLARE_SIMPLE_TYPE(NvmeBus, NVME_BUS)
485ffbaeedSKlaus Jensen 
495ffbaeedSKlaus Jensen typedef struct NvmeBus {
505ffbaeedSKlaus Jensen     BusState parent_bus;
515ffbaeedSKlaus Jensen } NvmeBus;
525ffbaeedSKlaus Jensen 
5388eea45cSKlaus Jensen #define TYPE_NVME_SUBSYS "nvme-subsys"
5488eea45cSKlaus Jensen #define NVME_SUBSYS(obj) \
5588eea45cSKlaus Jensen     OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS)
5699f48ae7SLukasz Maniak #define SUBSYS_SLOT_RSVD (void *)0xFFFF
5788eea45cSKlaus Jensen 
5873064edfSJesper Devantier typedef struct NvmeReclaimUnit {
5973064edfSJesper Devantier     uint64_t ruamw;
6073064edfSJesper Devantier } NvmeReclaimUnit;
6173064edfSJesper Devantier 
6273064edfSJesper Devantier typedef struct NvmeRuHandle {
6373064edfSJesper Devantier     uint8_t  ruht;
6473064edfSJesper Devantier     uint8_t  ruha;
6573064edfSJesper Devantier     uint64_t event_filter;
6673064edfSJesper Devantier     uint8_t  lbafi;
6773064edfSJesper Devantier     uint64_t ruamw;
6873064edfSJesper Devantier 
6973064edfSJesper Devantier     /* reclaim units indexed by reclaim group */
7073064edfSJesper Devantier     NvmeReclaimUnit *rus;
7173064edfSJesper Devantier } NvmeRuHandle;
7273064edfSJesper Devantier 
7373064edfSJesper Devantier typedef struct NvmeFdpEventBuffer {
7473064edfSJesper Devantier     NvmeFdpEvent     events[NVME_FDP_MAX_EVENTS];
7573064edfSJesper Devantier     unsigned int     nelems;
7673064edfSJesper Devantier     unsigned int     start;
7773064edfSJesper Devantier     unsigned int     next;
7873064edfSJesper Devantier } NvmeFdpEventBuffer;
7973064edfSJesper Devantier 
80771dbc3aSKlaus Jensen typedef struct NvmeEnduranceGroup {
81771dbc3aSKlaus Jensen     uint8_t event_conf;
8273064edfSJesper Devantier 
8373064edfSJesper Devantier     struct {
8473064edfSJesper Devantier         NvmeFdpEventBuffer host_events, ctrl_events;
8573064edfSJesper Devantier 
8673064edfSJesper Devantier         uint16_t nruh;
8773064edfSJesper Devantier         uint16_t nrg;
8873064edfSJesper Devantier         uint8_t  rgif;
8973064edfSJesper Devantier         uint64_t runs;
9073064edfSJesper Devantier 
9173064edfSJesper Devantier         uint64_t hbmw;
9273064edfSJesper Devantier         uint64_t mbmw;
9373064edfSJesper Devantier         uint64_t mbe;
9473064edfSJesper Devantier 
9573064edfSJesper Devantier         bool enabled;
9673064edfSJesper Devantier 
9773064edfSJesper Devantier         NvmeRuHandle *ruhs;
9873064edfSJesper Devantier     } fdp;
99771dbc3aSKlaus Jensen } NvmeEnduranceGroup;
100771dbc3aSKlaus Jensen 
10188eea45cSKlaus Jensen typedef struct NvmeSubsystem {
10288eea45cSKlaus Jensen     DeviceState parent_obj;
1035ffbaeedSKlaus Jensen     NvmeBus     bus;
10488eea45cSKlaus Jensen     uint8_t     subnqn[256];
105a859eb9fSKlaus Jensen     char        *serial;
10688eea45cSKlaus Jensen 
10788eea45cSKlaus Jensen     NvmeCtrl           *ctrls[NVME_MAX_CONTROLLERS];
10888eea45cSKlaus Jensen     NvmeNamespace      *namespaces[NVME_MAX_NAMESPACES + 1];
10973064edfSJesper Devantier     NvmeEnduranceGroup endgrp;
11088eea45cSKlaus Jensen 
11188eea45cSKlaus Jensen     struct {
11288eea45cSKlaus Jensen         char *nqn;
11373064edfSJesper Devantier 
11473064edfSJesper Devantier         struct {
11573064edfSJesper Devantier             bool     enabled;
11673064edfSJesper Devantier             uint64_t runs;
11773064edfSJesper Devantier             uint16_t nruh;
11873064edfSJesper Devantier             uint32_t nrg;
11973064edfSJesper Devantier         } fdp;
12088eea45cSKlaus Jensen     } params;
12188eea45cSKlaus Jensen } NvmeSubsystem;
12288eea45cSKlaus Jensen 
12388eea45cSKlaus Jensen int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp);
124b0fde9e8SKlaus Jensen void nvme_subsys_unregister_ctrl(NvmeSubsystem *subsys, NvmeCtrl *n);
12588eea45cSKlaus Jensen 
12688eea45cSKlaus Jensen static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys,
12788eea45cSKlaus Jensen                                          uint32_t cntlid)
12888eea45cSKlaus Jensen {
12988eea45cSKlaus Jensen     if (!subsys || cntlid >= NVME_MAX_CONTROLLERS) {
13088eea45cSKlaus Jensen         return NULL;
13188eea45cSKlaus Jensen     }
13288eea45cSKlaus Jensen 
13399f48ae7SLukasz Maniak     if (subsys->ctrls[cntlid] == SUBSYS_SLOT_RSVD) {
13499f48ae7SLukasz Maniak         return NULL;
13599f48ae7SLukasz Maniak     }
13699f48ae7SLukasz Maniak 
13788eea45cSKlaus Jensen     return subsys->ctrls[cntlid];
13888eea45cSKlaus Jensen }
13988eea45cSKlaus Jensen 
14088eea45cSKlaus Jensen static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
14188eea45cSKlaus Jensen                                             uint32_t nsid)
14288eea45cSKlaus Jensen {
14388eea45cSKlaus Jensen     if (!subsys || !nsid || nsid > NVME_MAX_NAMESPACES) {
14488eea45cSKlaus Jensen         return NULL;
14588eea45cSKlaus Jensen     }
14688eea45cSKlaus Jensen 
14788eea45cSKlaus Jensen     return subsys->namespaces[nsid];
14888eea45cSKlaus Jensen }
14988eea45cSKlaus Jensen 
15088eea45cSKlaus Jensen #define TYPE_NVME_NS "nvme-ns"
15188eea45cSKlaus Jensen #define NVME_NS(obj) \
15288eea45cSKlaus Jensen     OBJECT_CHECK(NvmeNamespace, (obj), TYPE_NVME_NS)
15388eea45cSKlaus Jensen 
15488eea45cSKlaus Jensen typedef struct NvmeZone {
15588eea45cSKlaus Jensen     NvmeZoneDescr   d;
15688eea45cSKlaus Jensen     uint64_t        w_ptr;
15788eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeZone) entry;
15888eea45cSKlaus Jensen } NvmeZone;
15988eea45cSKlaus Jensen 
16073064edfSJesper Devantier #define FDP_EVT_MAX 0xff
16173064edfSJesper Devantier #define NVME_FDP_MAX_NS_RUHS 32u
16273064edfSJesper Devantier #define FDPVSS 0
16373064edfSJesper Devantier 
16473064edfSJesper Devantier static const uint8_t nvme_fdp_evf_shifts[FDP_EVT_MAX] = {
16573064edfSJesper Devantier     /* Host events */
16673064edfSJesper Devantier     [FDP_EVT_RU_NOT_FULLY_WRITTEN]      = 0,
16773064edfSJesper Devantier     [FDP_EVT_RU_ATL_EXCEEDED]           = 1,
16873064edfSJesper Devantier     [FDP_EVT_CTRL_RESET_RUH]            = 2,
16973064edfSJesper Devantier     [FDP_EVT_INVALID_PID]               = 3,
17073064edfSJesper Devantier     /* CTRL events */
17173064edfSJesper Devantier     [FDP_EVT_MEDIA_REALLOC]             = 32,
17273064edfSJesper Devantier     [FDP_EVT_RUH_IMPLICIT_RU_CHANGE]    = 33,
17373064edfSJesper Devantier };
17473064edfSJesper Devantier 
175bdc31646SRoque Arcudia Hernandez #define NGUID_LEN 16
176bdc31646SRoque Arcudia Hernandez 
177bdc31646SRoque Arcudia Hernandez typedef struct {
178bdc31646SRoque Arcudia Hernandez     uint8_t data[NGUID_LEN];
179bdc31646SRoque Arcudia Hernandez } NvmeNGUID;
180bdc31646SRoque Arcudia Hernandez 
181bdc31646SRoque Arcudia Hernandez bool nvme_nguid_is_null(const NvmeNGUID *nguid);
182bdc31646SRoque Arcudia Hernandez 
183bdc31646SRoque Arcudia Hernandez extern const PropertyInfo qdev_prop_nguid;
184bdc31646SRoque Arcudia Hernandez 
185bdc31646SRoque Arcudia Hernandez #define DEFINE_PROP_NGUID_NODEFAULT(_name, _state, _field) \
186bdc31646SRoque Arcudia Hernandez     DEFINE_PROP(_name, _state, _field, qdev_prop_nguid, NvmeNGUID)
187bdc31646SRoque Arcudia Hernandez 
18888eea45cSKlaus Jensen typedef struct NvmeNamespaceParams {
18988eea45cSKlaus Jensen     bool      detached;
19088eea45cSKlaus Jensen     bool      shared;
19188eea45cSKlaus Jensen     uint32_t  nsid;
19288eea45cSKlaus Jensen     QemuUUID  uuid;
193bdc31646SRoque Arcudia Hernandez     NvmeNGUID nguid;
1946870cfb8SHeinrich Schuchardt     uint64_t  eui64;
1953276dde4SHeinrich Schuchardt     bool      eui64_default;
19688eea45cSKlaus Jensen 
19788eea45cSKlaus Jensen     uint16_t ms;
19888eea45cSKlaus Jensen     uint8_t  mset;
19988eea45cSKlaus Jensen     uint8_t  pi;
20088eea45cSKlaus Jensen     uint8_t  pil;
20144219b60SNaveen Nagar     uint8_t  pif;
20288eea45cSKlaus Jensen 
20388eea45cSKlaus Jensen     uint16_t mssrl;
20488eea45cSKlaus Jensen     uint32_t mcl;
20588eea45cSKlaus Jensen     uint8_t  msrc;
20688eea45cSKlaus Jensen 
20788eea45cSKlaus Jensen     bool     zoned;
20888eea45cSKlaus Jensen     bool     cross_zone_read;
20988eea45cSKlaus Jensen     uint64_t zone_size_bs;
21088eea45cSKlaus Jensen     uint64_t zone_cap_bs;
21188eea45cSKlaus Jensen     uint32_t max_active_zones;
21288eea45cSKlaus Jensen     uint32_t max_open_zones;
21388eea45cSKlaus Jensen     uint32_t zd_extension_size;
214e321b4cdSKlaus Jensen 
215e321b4cdSKlaus Jensen     uint32_t numzrwa;
216e321b4cdSKlaus Jensen     uint64_t zrwas;
217e321b4cdSKlaus Jensen     uint64_t zrwafg;
21873064edfSJesper Devantier 
21973064edfSJesper Devantier     struct {
22073064edfSJesper Devantier         char *ruhs;
22173064edfSJesper Devantier     } fdp;
22288eea45cSKlaus Jensen } NvmeNamespaceParams;
22388eea45cSKlaus Jensen 
22488eea45cSKlaus Jensen typedef struct NvmeNamespace {
22588eea45cSKlaus Jensen     DeviceState  parent_obj;
22688eea45cSKlaus Jensen     BlockConf    blkconf;
22788eea45cSKlaus Jensen     int32_t      bootindex;
22888eea45cSKlaus Jensen     int64_t      size;
22988eea45cSKlaus Jensen     int64_t      moff;
23088eea45cSKlaus Jensen     NvmeIdNs     id_ns;
23144219b60SNaveen Nagar     NvmeIdNsNvm  id_ns_nvm;
23288eea45cSKlaus Jensen     NvmeLBAF     lbaf;
233763c05dfSNaveen Nagar     unsigned int nlbaf;
23488eea45cSKlaus Jensen     size_t       lbasz;
23588eea45cSKlaus Jensen     const uint32_t *iocs;
23688eea45cSKlaus Jensen     uint8_t      csi;
23788eea45cSKlaus Jensen     uint16_t     status;
23888eea45cSKlaus Jensen     int          attached;
23944219b60SNaveen Nagar     uint8_t      pif;
24088eea45cSKlaus Jensen 
241e321b4cdSKlaus Jensen     struct {
242e321b4cdSKlaus Jensen         uint16_t zrwas;
243e321b4cdSKlaus Jensen         uint16_t zrwafg;
244e321b4cdSKlaus Jensen         uint32_t numzrwa;
245e321b4cdSKlaus Jensen     } zns;
246e321b4cdSKlaus Jensen 
24788eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeNamespace) entry;
24888eea45cSKlaus Jensen 
24988eea45cSKlaus Jensen     NvmeIdNsZoned   *id_ns_zoned;
25088eea45cSKlaus Jensen     NvmeZone        *zone_array;
25188eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) exp_open_zones;
25288eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) imp_open_zones;
25388eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) closed_zones;
25488eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeZone) full_zones;
25588eea45cSKlaus Jensen     uint32_t        num_zones;
25688eea45cSKlaus Jensen     uint64_t        zone_size;
25788eea45cSKlaus Jensen     uint64_t        zone_capacity;
25888eea45cSKlaus Jensen     uint32_t        zone_size_log2;
25988eea45cSKlaus Jensen     uint8_t         *zd_extensions;
26088eea45cSKlaus Jensen     int32_t         nr_open_zones;
26188eea45cSKlaus Jensen     int32_t         nr_active_zones;
26288eea45cSKlaus Jensen 
26388eea45cSKlaus Jensen     NvmeNamespaceParams params;
264534a93d3SNiklas Cassel     NvmeSubsystem *subsys;
26573064edfSJesper Devantier     NvmeEnduranceGroup *endgrp;
26688eea45cSKlaus Jensen 
26788eea45cSKlaus Jensen     struct {
26888eea45cSKlaus Jensen         uint32_t err_rec;
26988eea45cSKlaus Jensen     } features;
27073064edfSJesper Devantier 
27173064edfSJesper Devantier     struct {
27273064edfSJesper Devantier         uint16_t nphs;
27373064edfSJesper Devantier         /* reclaim unit handle identifiers indexed by placement handle */
27473064edfSJesper Devantier         uint16_t *phs;
27573064edfSJesper Devantier     } fdp;
27688eea45cSKlaus Jensen } NvmeNamespace;
27788eea45cSKlaus Jensen 
27888eea45cSKlaus Jensen static inline uint32_t nvme_nsid(NvmeNamespace *ns)
27988eea45cSKlaus Jensen {
28088eea45cSKlaus Jensen     if (ns) {
28188eea45cSKlaus Jensen         return ns->params.nsid;
28288eea45cSKlaus Jensen     }
28388eea45cSKlaus Jensen 
28488eea45cSKlaus Jensen     return 0;
28588eea45cSKlaus Jensen }
28688eea45cSKlaus Jensen 
28788eea45cSKlaus Jensen static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba)
28888eea45cSKlaus Jensen {
28988eea45cSKlaus Jensen     return lba << ns->lbaf.ds;
29088eea45cSKlaus Jensen }
29188eea45cSKlaus Jensen 
29288eea45cSKlaus Jensen static inline size_t nvme_m2b(NvmeNamespace *ns, uint64_t lba)
29388eea45cSKlaus Jensen {
29488eea45cSKlaus Jensen     return ns->lbaf.ms * lba;
29588eea45cSKlaus Jensen }
29688eea45cSKlaus Jensen 
29788eea45cSKlaus Jensen static inline int64_t nvme_moff(NvmeNamespace *ns, uint64_t lba)
29888eea45cSKlaus Jensen {
29988eea45cSKlaus Jensen     return ns->moff + nvme_m2b(ns, lba);
30088eea45cSKlaus Jensen }
30188eea45cSKlaus Jensen 
30288eea45cSKlaus Jensen static inline bool nvme_ns_ext(NvmeNamespace *ns)
30388eea45cSKlaus Jensen {
30488eea45cSKlaus Jensen     return !!NVME_ID_NS_FLBAS_EXTENDED(ns->id_ns.flbas);
30588eea45cSKlaus Jensen }
30688eea45cSKlaus Jensen 
30788eea45cSKlaus Jensen static inline NvmeZoneState nvme_get_zone_state(NvmeZone *zone)
30888eea45cSKlaus Jensen {
30988eea45cSKlaus Jensen     return zone->d.zs >> 4;
31088eea45cSKlaus Jensen }
31188eea45cSKlaus Jensen 
31288eea45cSKlaus Jensen static inline void nvme_set_zone_state(NvmeZone *zone, NvmeZoneState state)
31388eea45cSKlaus Jensen {
31488eea45cSKlaus Jensen     zone->d.zs = state << 4;
31588eea45cSKlaus Jensen }
31688eea45cSKlaus Jensen 
31788eea45cSKlaus Jensen static inline uint64_t nvme_zone_rd_boundary(NvmeNamespace *ns, NvmeZone *zone)
31888eea45cSKlaus Jensen {
31988eea45cSKlaus Jensen     return zone->d.zslba + ns->zone_size;
32088eea45cSKlaus Jensen }
32188eea45cSKlaus Jensen 
32288eea45cSKlaus Jensen static inline uint64_t nvme_zone_wr_boundary(NvmeZone *zone)
32388eea45cSKlaus Jensen {
32488eea45cSKlaus Jensen     return zone->d.zslba + zone->d.zcap;
32588eea45cSKlaus Jensen }
32688eea45cSKlaus Jensen 
32788eea45cSKlaus Jensen static inline bool nvme_wp_is_valid(NvmeZone *zone)
32888eea45cSKlaus Jensen {
32988eea45cSKlaus Jensen     uint8_t st = nvme_get_zone_state(zone);
33088eea45cSKlaus Jensen 
33188eea45cSKlaus Jensen     return st != NVME_ZONE_STATE_FULL &&
33288eea45cSKlaus Jensen            st != NVME_ZONE_STATE_READ_ONLY &&
33388eea45cSKlaus Jensen            st != NVME_ZONE_STATE_OFFLINE;
33488eea45cSKlaus Jensen }
33588eea45cSKlaus Jensen 
33688eea45cSKlaus Jensen static inline uint8_t *nvme_get_zd_extension(NvmeNamespace *ns,
33788eea45cSKlaus Jensen                                              uint32_t zone_idx)
33888eea45cSKlaus Jensen {
33988eea45cSKlaus Jensen     return &ns->zd_extensions[zone_idx * ns->params.zd_extension_size];
34088eea45cSKlaus Jensen }
34188eea45cSKlaus Jensen 
34288eea45cSKlaus Jensen static inline void nvme_aor_inc_open(NvmeNamespace *ns)
34388eea45cSKlaus Jensen {
34488eea45cSKlaus Jensen     assert(ns->nr_open_zones >= 0);
34588eea45cSKlaus Jensen     if (ns->params.max_open_zones) {
34688eea45cSKlaus Jensen         ns->nr_open_zones++;
34788eea45cSKlaus Jensen         assert(ns->nr_open_zones <= ns->params.max_open_zones);
34888eea45cSKlaus Jensen     }
34988eea45cSKlaus Jensen }
35088eea45cSKlaus Jensen 
35188eea45cSKlaus Jensen static inline void nvme_aor_dec_open(NvmeNamespace *ns)
35288eea45cSKlaus Jensen {
35388eea45cSKlaus Jensen     if (ns->params.max_open_zones) {
35488eea45cSKlaus Jensen         assert(ns->nr_open_zones > 0);
35588eea45cSKlaus Jensen         ns->nr_open_zones--;
35688eea45cSKlaus Jensen     }
35788eea45cSKlaus Jensen     assert(ns->nr_open_zones >= 0);
35888eea45cSKlaus Jensen }
35988eea45cSKlaus Jensen 
36088eea45cSKlaus Jensen static inline void nvme_aor_inc_active(NvmeNamespace *ns)
36188eea45cSKlaus Jensen {
36288eea45cSKlaus Jensen     assert(ns->nr_active_zones >= 0);
36388eea45cSKlaus Jensen     if (ns->params.max_active_zones) {
36488eea45cSKlaus Jensen         ns->nr_active_zones++;
36588eea45cSKlaus Jensen         assert(ns->nr_active_zones <= ns->params.max_active_zones);
36688eea45cSKlaus Jensen     }
36788eea45cSKlaus Jensen }
36888eea45cSKlaus Jensen 
36988eea45cSKlaus Jensen static inline void nvme_aor_dec_active(NvmeNamespace *ns)
37088eea45cSKlaus Jensen {
37188eea45cSKlaus Jensen     if (ns->params.max_active_zones) {
37288eea45cSKlaus Jensen         assert(ns->nr_active_zones > 0);
37388eea45cSKlaus Jensen         ns->nr_active_zones--;
37488eea45cSKlaus Jensen         assert(ns->nr_active_zones >= ns->nr_open_zones);
37588eea45cSKlaus Jensen     }
37688eea45cSKlaus Jensen     assert(ns->nr_active_zones >= 0);
37788eea45cSKlaus Jensen }
37888eea45cSKlaus Jensen 
37973064edfSJesper Devantier static inline void nvme_fdp_stat_inc(uint64_t *a, uint64_t b)
38073064edfSJesper Devantier {
38173064edfSJesper Devantier     uint64_t ret = *a + b;
38273064edfSJesper Devantier     *a = ret < *a ? UINT64_MAX : ret;
38373064edfSJesper Devantier }
38473064edfSJesper Devantier 
38588eea45cSKlaus Jensen void nvme_ns_init_format(NvmeNamespace *ns);
3865e4f6bccSKlaus Jensen int nvme_ns_setup(NvmeNamespace *ns, Error **errp);
38788eea45cSKlaus Jensen void nvme_ns_drain(NvmeNamespace *ns);
38888eea45cSKlaus Jensen void nvme_ns_shutdown(NvmeNamespace *ns);
38988eea45cSKlaus Jensen void nvme_ns_cleanup(NvmeNamespace *ns);
39088eea45cSKlaus Jensen 
39188eea45cSKlaus Jensen typedef struct NvmeAsyncEvent {
39288eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeAsyncEvent) entry;
39388eea45cSKlaus Jensen     NvmeAerResult result;
39488eea45cSKlaus Jensen } NvmeAsyncEvent;
39588eea45cSKlaus Jensen 
39688eea45cSKlaus Jensen enum {
39788eea45cSKlaus Jensen     NVME_SG_ALLOC = 1 << 0,
39888eea45cSKlaus Jensen     NVME_SG_DMA   = 1 << 1,
39988eea45cSKlaus Jensen };
40088eea45cSKlaus Jensen 
40188eea45cSKlaus Jensen typedef struct NvmeSg {
40288eea45cSKlaus Jensen     int flags;
40388eea45cSKlaus Jensen 
40488eea45cSKlaus Jensen     union {
40588eea45cSKlaus Jensen         QEMUSGList   qsg;
40688eea45cSKlaus Jensen         QEMUIOVector iov;
40788eea45cSKlaus Jensen     };
40888eea45cSKlaus Jensen } NvmeSg;
40988eea45cSKlaus Jensen 
41088eea45cSKlaus Jensen typedef enum NvmeTxDirection {
41188eea45cSKlaus Jensen     NVME_TX_DIRECTION_TO_DEVICE   = 0,
41288eea45cSKlaus Jensen     NVME_TX_DIRECTION_FROM_DEVICE = 1,
41388eea45cSKlaus Jensen } NvmeTxDirection;
41488eea45cSKlaus Jensen 
41588eea45cSKlaus Jensen typedef struct NvmeRequest {
41688eea45cSKlaus Jensen     struct NvmeSQueue       *sq;
41788eea45cSKlaus Jensen     struct NvmeNamespace    *ns;
41888eea45cSKlaus Jensen     BlockAIOCB              *aiocb;
41988eea45cSKlaus Jensen     uint16_t                status;
42088eea45cSKlaus Jensen     void                    *opaque;
42188eea45cSKlaus Jensen     NvmeCqe                 cqe;
42288eea45cSKlaus Jensen     NvmeCmd                 cmd;
42388eea45cSKlaus Jensen     BlockAcctCookie         acct;
42488eea45cSKlaus Jensen     NvmeSg                  sg;
42588eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeRequest)entry;
42688eea45cSKlaus Jensen } NvmeRequest;
42788eea45cSKlaus Jensen 
42888eea45cSKlaus Jensen typedef struct NvmeBounceContext {
42988eea45cSKlaus Jensen     NvmeRequest *req;
43088eea45cSKlaus Jensen 
43188eea45cSKlaus Jensen     struct {
43288eea45cSKlaus Jensen         QEMUIOVector iov;
43388eea45cSKlaus Jensen         uint8_t *bounce;
43488eea45cSKlaus Jensen     } data, mdata;
43588eea45cSKlaus Jensen } NvmeBounceContext;
43688eea45cSKlaus Jensen 
43788eea45cSKlaus Jensen static inline const char *nvme_adm_opc_str(uint8_t opc)
43888eea45cSKlaus Jensen {
43988eea45cSKlaus Jensen     switch (opc) {
44088eea45cSKlaus Jensen     case NVME_ADM_CMD_DELETE_SQ:        return "NVME_ADM_CMD_DELETE_SQ";
44188eea45cSKlaus Jensen     case NVME_ADM_CMD_CREATE_SQ:        return "NVME_ADM_CMD_CREATE_SQ";
44288eea45cSKlaus Jensen     case NVME_ADM_CMD_GET_LOG_PAGE:     return "NVME_ADM_CMD_GET_LOG_PAGE";
44388eea45cSKlaus Jensen     case NVME_ADM_CMD_DELETE_CQ:        return "NVME_ADM_CMD_DELETE_CQ";
44488eea45cSKlaus Jensen     case NVME_ADM_CMD_CREATE_CQ:        return "NVME_ADM_CMD_CREATE_CQ";
44588eea45cSKlaus Jensen     case NVME_ADM_CMD_IDENTIFY:         return "NVME_ADM_CMD_IDENTIFY";
44688eea45cSKlaus Jensen     case NVME_ADM_CMD_ABORT:            return "NVME_ADM_CMD_ABORT";
44788eea45cSKlaus Jensen     case NVME_ADM_CMD_SET_FEATURES:     return "NVME_ADM_CMD_SET_FEATURES";
44888eea45cSKlaus Jensen     case NVME_ADM_CMD_GET_FEATURES:     return "NVME_ADM_CMD_GET_FEATURES";
44988eea45cSKlaus Jensen     case NVME_ADM_CMD_ASYNC_EV_REQ:     return "NVME_ADM_CMD_ASYNC_EV_REQ";
45088eea45cSKlaus Jensen     case NVME_ADM_CMD_NS_ATTACHMENT:    return "NVME_ADM_CMD_NS_ATTACHMENT";
451e181d3daSGollu Appalanaidu     case NVME_ADM_CMD_DIRECTIVE_SEND:   return "NVME_ADM_CMD_DIRECTIVE_SEND";
45211871f53SŁukasz Gieryk     case NVME_ADM_CMD_VIRT_MNGMT:       return "NVME_ADM_CMD_VIRT_MNGMT";
453e181d3daSGollu Appalanaidu     case NVME_ADM_CMD_DIRECTIVE_RECV:   return "NVME_ADM_CMD_DIRECTIVE_RECV";
4543f7fe8deSJinhao Fan     case NVME_ADM_CMD_DBBUF_CONFIG:     return "NVME_ADM_CMD_DBBUF_CONFIG";
45588eea45cSKlaus Jensen     case NVME_ADM_CMD_FORMAT_NVM:       return "NVME_ADM_CMD_FORMAT_NVM";
45688eea45cSKlaus Jensen     default:                            return "NVME_ADM_CMD_UNKNOWN";
45788eea45cSKlaus Jensen     }
45888eea45cSKlaus Jensen }
45988eea45cSKlaus Jensen 
46088eea45cSKlaus Jensen static inline const char *nvme_io_opc_str(uint8_t opc)
46188eea45cSKlaus Jensen {
46288eea45cSKlaus Jensen     switch (opc) {
46388eea45cSKlaus Jensen     case NVME_CMD_FLUSH:            return "NVME_NVM_CMD_FLUSH";
46488eea45cSKlaus Jensen     case NVME_CMD_WRITE:            return "NVME_NVM_CMD_WRITE";
46588eea45cSKlaus Jensen     case NVME_CMD_READ:             return "NVME_NVM_CMD_READ";
46688eea45cSKlaus Jensen     case NVME_CMD_COMPARE:          return "NVME_NVM_CMD_COMPARE";
46788eea45cSKlaus Jensen     case NVME_CMD_WRITE_ZEROES:     return "NVME_NVM_CMD_WRITE_ZEROES";
46888eea45cSKlaus Jensen     case NVME_CMD_DSM:              return "NVME_NVM_CMD_DSM";
46988eea45cSKlaus Jensen     case NVME_CMD_VERIFY:           return "NVME_NVM_CMD_VERIFY";
47088eea45cSKlaus Jensen     case NVME_CMD_COPY:             return "NVME_NVM_CMD_COPY";
47188eea45cSKlaus Jensen     case NVME_CMD_ZONE_MGMT_SEND:   return "NVME_ZONED_CMD_MGMT_SEND";
47288eea45cSKlaus Jensen     case NVME_CMD_ZONE_MGMT_RECV:   return "NVME_ZONED_CMD_MGMT_RECV";
47388eea45cSKlaus Jensen     case NVME_CMD_ZONE_APPEND:      return "NVME_ZONED_CMD_ZONE_APPEND";
47488eea45cSKlaus Jensen     default:                        return "NVME_NVM_CMD_UNKNOWN";
47588eea45cSKlaus Jensen     }
47688eea45cSKlaus Jensen }
47788eea45cSKlaus Jensen 
47888eea45cSKlaus Jensen typedef struct NvmeSQueue {
47988eea45cSKlaus Jensen     struct NvmeCtrl *ctrl;
48088eea45cSKlaus Jensen     uint16_t    sqid;
48188eea45cSKlaus Jensen     uint16_t    cqid;
48288eea45cSKlaus Jensen     uint32_t    head;
48388eea45cSKlaus Jensen     uint32_t    tail;
48488eea45cSKlaus Jensen     uint32_t    size;
48588eea45cSKlaus Jensen     uint64_t    dma_addr;
4863f7fe8deSJinhao Fan     uint64_t    db_addr;
4873f7fe8deSJinhao Fan     uint64_t    ei_addr;
488d38cc6fdSKlaus Jensen     QEMUBH      *bh;
4892e53b0b4SJinhao Fan     EventNotifier notifier;
4902e53b0b4SJinhao Fan     bool        ioeventfd_enabled;
49188eea45cSKlaus Jensen     NvmeRequest *io_req;
49288eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeRequest) req_list;
49388eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeRequest) out_req_list;
49488eea45cSKlaus Jensen     QTAILQ_ENTRY(NvmeSQueue) entry;
49588eea45cSKlaus Jensen } NvmeSQueue;
49688eea45cSKlaus Jensen 
49788eea45cSKlaus Jensen typedef struct NvmeCQueue {
49888eea45cSKlaus Jensen     struct NvmeCtrl *ctrl;
49988eea45cSKlaus Jensen     uint8_t     phase;
50088eea45cSKlaus Jensen     uint16_t    cqid;
50188eea45cSKlaus Jensen     uint16_t    irq_enabled;
50288eea45cSKlaus Jensen     uint32_t    head;
50388eea45cSKlaus Jensen     uint32_t    tail;
50488eea45cSKlaus Jensen     uint32_t    vector;
50588eea45cSKlaus Jensen     uint32_t    size;
50688eea45cSKlaus Jensen     uint64_t    dma_addr;
5073f7fe8deSJinhao Fan     uint64_t    db_addr;
5083f7fe8deSJinhao Fan     uint64_t    ei_addr;
509d38cc6fdSKlaus Jensen     QEMUBH      *bh;
5102e53b0b4SJinhao Fan     EventNotifier notifier;
5112e53b0b4SJinhao Fan     bool        ioeventfd_enabled;
51288eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeSQueue) sq_list;
51388eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeRequest) req_list;
51488eea45cSKlaus Jensen } NvmeCQueue;
51588eea45cSKlaus Jensen 
51688eea45cSKlaus Jensen #define TYPE_NVME "nvme"
51788eea45cSKlaus Jensen #define NVME(obj) \
51888eea45cSKlaus Jensen         OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME)
51988eea45cSKlaus Jensen 
52088eea45cSKlaus Jensen typedef struct NvmeParams {
52188eea45cSKlaus Jensen     char     *serial;
52288eea45cSKlaus Jensen     uint32_t num_queues; /* deprecated since 5.1 */
52388eea45cSKlaus Jensen     uint32_t max_ioqpairs;
52488eea45cSKlaus Jensen     uint16_t msix_qsize;
525bc432bc5SJohn Berg     uint16_t mqes;
52688eea45cSKlaus Jensen     uint32_t cmb_size_mb;
52788eea45cSKlaus Jensen     uint8_t  aerl;
52888eea45cSKlaus Jensen     uint32_t aer_max_queued;
52988eea45cSKlaus Jensen     uint8_t  mdts;
53088eea45cSKlaus Jensen     uint8_t  vsl;
53188eea45cSKlaus Jensen     bool     use_intel_id;
53288eea45cSKlaus Jensen     uint8_t  zasl;
533cccc2651SNiklas Cassel     bool     auto_transition_zones;
53488eea45cSKlaus Jensen     bool     legacy_cmb;
5352e53b0b4SJinhao Fan     bool     ioeventfd;
53644c2c094SLukasz Maniak     uint8_t  sriov_max_vfs;
537746d42b1SŁukasz Gieryk     uint16_t sriov_vq_flexible;
538746d42b1SŁukasz Gieryk     uint16_t sriov_vi_flexible;
539746d42b1SŁukasz Gieryk     uint8_t  sriov_max_vq_per_vf;
540746d42b1SŁukasz Gieryk     uint8_t  sriov_max_vi_per_vf;
541fa905f65SKlaus Jensen     bool     msix_exclusive_bar;
54288eea45cSKlaus Jensen } NvmeParams;
54388eea45cSKlaus Jensen 
54488eea45cSKlaus Jensen typedef struct NvmeCtrl {
54588eea45cSKlaus Jensen     PCIDevice    parent_obj;
54688eea45cSKlaus Jensen     MemoryRegion bar0;
54788eea45cSKlaus Jensen     MemoryRegion iomem;
54888eea45cSKlaus Jensen     NvmeBar      bar;
54988eea45cSKlaus Jensen     NvmeParams   params;
55088eea45cSKlaus Jensen     NvmeBus      bus;
55188eea45cSKlaus Jensen 
55288eea45cSKlaus Jensen     uint16_t    cntlid;
55388eea45cSKlaus Jensen     bool        qs_created;
55488eea45cSKlaus Jensen     uint32_t    page_size;
55588eea45cSKlaus Jensen     uint16_t    page_bits;
55688eea45cSKlaus Jensen     uint16_t    max_prp_ents;
55788eea45cSKlaus Jensen     uint32_t    max_q_ents;
55888eea45cSKlaus Jensen     uint8_t     outstanding_aers;
55988eea45cSKlaus Jensen     uint32_t    irq_status;
56083d7ed5cSKlaus Jensen     int         cq_pending;
56188eea45cSKlaus Jensen     uint64_t    host_timestamp;                 /* Timestamp sent by the host */
56288eea45cSKlaus Jensen     uint64_t    timestamp_set_qemu_clock_ms;    /* QEMU clock time */
56388eea45cSKlaus Jensen     uint64_t    starttime_ms;
56488eea45cSKlaus Jensen     uint16_t    temperature;
56588eea45cSKlaus Jensen     uint8_t     smart_critical_warning;
566decc0261SŁukasz Gieryk     uint32_t    conf_msix_qsize;
567decc0261SŁukasz Gieryk     uint32_t    conf_ioqpairs;
5683f7fe8deSJinhao Fan     uint64_t    dbbuf_dbs;
5693f7fe8deSJinhao Fan     uint64_t    dbbuf_eis;
5703f7fe8deSJinhao Fan     bool        dbbuf_enabled;
57188eea45cSKlaus Jensen 
57288eea45cSKlaus Jensen     struct {
57388eea45cSKlaus Jensen         MemoryRegion mem;
57488eea45cSKlaus Jensen         uint8_t      *buf;
57588eea45cSKlaus Jensen         bool         cmse;
57688eea45cSKlaus Jensen         hwaddr       cba;
57788eea45cSKlaus Jensen     } cmb;
57888eea45cSKlaus Jensen 
57988eea45cSKlaus Jensen     struct {
58088eea45cSKlaus Jensen         HostMemoryBackend *dev;
58188eea45cSKlaus Jensen         bool              cmse;
58288eea45cSKlaus Jensen         hwaddr            cba;
58388eea45cSKlaus Jensen     } pmr;
58488eea45cSKlaus Jensen 
58588eea45cSKlaus Jensen     uint8_t     aer_mask;
58688eea45cSKlaus Jensen     NvmeRequest **aer_reqs;
58788eea45cSKlaus Jensen     QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue;
58888eea45cSKlaus Jensen     int         aer_queued;
58988eea45cSKlaus Jensen 
59088eea45cSKlaus Jensen     uint32_t    dmrsl;
59188eea45cSKlaus Jensen 
59288eea45cSKlaus Jensen     /* Namespace ID is started with 1 so bitmap should be 1-based */
59388eea45cSKlaus Jensen #define NVME_CHANGED_NSID_SIZE  (NVME_MAX_NAMESPACES + 1)
59488eea45cSKlaus Jensen     DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE);
59588eea45cSKlaus Jensen 
59688eea45cSKlaus Jensen     NvmeSubsystem   *subsys;
59788eea45cSKlaus Jensen 
59888eea45cSKlaus Jensen     NvmeNamespace   namespace;
59988eea45cSKlaus Jensen     NvmeNamespace   *namespaces[NVME_MAX_NAMESPACES + 1];
60088eea45cSKlaus Jensen     NvmeSQueue      **sq;
60188eea45cSKlaus Jensen     NvmeCQueue      **cq;
60288eea45cSKlaus Jensen     NvmeSQueue      admin_sq;
60388eea45cSKlaus Jensen     NvmeCQueue      admin_cq;
60488eea45cSKlaus Jensen     NvmeIdCtrl      id_ctrl;
60588eea45cSKlaus Jensen 
60688eea45cSKlaus Jensen     struct {
60788eea45cSKlaus Jensen         struct {
60888eea45cSKlaus Jensen             uint16_t temp_thresh_hi;
60988eea45cSKlaus Jensen             uint16_t temp_thresh_low;
61088eea45cSKlaus Jensen         };
611d0c0697bSNaveen Nagar 
61288eea45cSKlaus Jensen         uint32_t                async_config;
613d0c0697bSNaveen Nagar         NvmeHostBehaviorSupport hbs;
61488eea45cSKlaus Jensen     } features;
6155e6f963fSLukasz Maniak 
6165e6f963fSLukasz Maniak     NvmePriCtrlCap  pri_ctrl_cap;
617*1a494d11SMinwoo Im     uint32_t nr_sec_ctrls;
618*1a494d11SMinwoo Im     NvmeSecCtrlEntry sec_ctrl_list[NVME_MAX_VFS];
61911871f53SŁukasz Gieryk     struct {
62011871f53SŁukasz Gieryk         uint16_t    vqrfap;
62111871f53SŁukasz Gieryk         uint16_t    virfap;
62211871f53SŁukasz Gieryk     } next_pri_ctrl_cap;    /* These override pri_ctrl_cap after reset */
62388eea45cSKlaus Jensen } NvmeCtrl;
62488eea45cSKlaus Jensen 
6251e9c685eSŁukasz Gieryk typedef enum NvmeResetType {
6261e9c685eSŁukasz Gieryk     NVME_RESET_FUNCTION   = 0,
6271e9c685eSŁukasz Gieryk     NVME_RESET_CONTROLLER = 1,
6281e9c685eSŁukasz Gieryk } NvmeResetType;
6291e9c685eSŁukasz Gieryk 
63088eea45cSKlaus Jensen static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
63188eea45cSKlaus Jensen {
63288eea45cSKlaus Jensen     if (!nsid || nsid > NVME_MAX_NAMESPACES) {
63388eea45cSKlaus Jensen         return NULL;
63488eea45cSKlaus Jensen     }
63588eea45cSKlaus Jensen 
63688eea45cSKlaus Jensen     return n->namespaces[nsid];
63788eea45cSKlaus Jensen }
63888eea45cSKlaus Jensen 
63988eea45cSKlaus Jensen static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
64088eea45cSKlaus Jensen {
64188eea45cSKlaus Jensen     NvmeSQueue *sq = req->sq;
64288eea45cSKlaus Jensen     NvmeCtrl *n = sq->ctrl;
64388eea45cSKlaus Jensen 
64488eea45cSKlaus Jensen     return n->cq[sq->cqid];
64588eea45cSKlaus Jensen }
64688eea45cSKlaus Jensen 
64788eea45cSKlaus Jensen static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req)
64888eea45cSKlaus Jensen {
64988eea45cSKlaus Jensen     NvmeSQueue *sq = req->sq;
65088eea45cSKlaus Jensen     return sq->ctrl;
65188eea45cSKlaus Jensen }
65288eea45cSKlaus Jensen 
65388eea45cSKlaus Jensen static inline uint16_t nvme_cid(NvmeRequest *req)
65488eea45cSKlaus Jensen {
65588eea45cSKlaus Jensen     if (!req) {
65688eea45cSKlaus Jensen         return 0xffff;
65788eea45cSKlaus Jensen     }
65888eea45cSKlaus Jensen 
65988eea45cSKlaus Jensen     return le16_to_cpu(req->cqe.cid);
66088eea45cSKlaus Jensen }
66188eea45cSKlaus Jensen 
66299f48ae7SLukasz Maniak static inline NvmeSecCtrlEntry *nvme_sctrl(NvmeCtrl *n)
66399f48ae7SLukasz Maniak {
66499f48ae7SLukasz Maniak     PCIDevice *pci_dev = &n->parent_obj;
66599f48ae7SLukasz Maniak     NvmeCtrl *pf = NVME(pcie_sriov_get_pf(pci_dev));
66699f48ae7SLukasz Maniak 
66799f48ae7SLukasz Maniak     if (pci_is_vf(pci_dev)) {
668*1a494d11SMinwoo Im         return &pf->sec_ctrl_list[pcie_sriov_vf_number(pci_dev)];
66999f48ae7SLukasz Maniak     }
67099f48ae7SLukasz Maniak 
67199f48ae7SLukasz Maniak     return NULL;
67299f48ae7SLukasz Maniak }
67399f48ae7SLukasz Maniak 
67411871f53SŁukasz Gieryk static inline NvmeSecCtrlEntry *nvme_sctrl_for_cntlid(NvmeCtrl *n,
67511871f53SŁukasz Gieryk                                                       uint16_t cntlid)
67611871f53SŁukasz Gieryk {
677*1a494d11SMinwoo Im     NvmeSecCtrlEntry *list = n->sec_ctrl_list;
67811871f53SŁukasz Gieryk     uint8_t i;
67911871f53SŁukasz Gieryk 
680*1a494d11SMinwoo Im     for (i = 0; i < n->nr_sec_ctrls; i++) {
681*1a494d11SMinwoo Im         if (le16_to_cpu(list[i].scid) == cntlid) {
682*1a494d11SMinwoo Im             return &list[i];
68311871f53SŁukasz Gieryk         }
68411871f53SŁukasz Gieryk     }
68511871f53SŁukasz Gieryk 
68611871f53SŁukasz Gieryk     return NULL;
68711871f53SŁukasz Gieryk }
68811871f53SŁukasz Gieryk 
68988eea45cSKlaus Jensen void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns);
6908d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_data(NvmeCtrl *n, void *ptr, uint32_t len,
69188eea45cSKlaus Jensen                           NvmeTxDirection dir, NvmeRequest *req);
6928d3a17beSPhilippe Mathieu-Daudé uint16_t nvme_bounce_mdata(NvmeCtrl *n, void *ptr, uint32_t len,
69388eea45cSKlaus Jensen                            NvmeTxDirection dir, NvmeRequest *req);
69488eea45cSKlaus Jensen void nvme_rw_complete_cb(void *opaque, int ret);
69588eea45cSKlaus Jensen uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len,
69688eea45cSKlaus Jensen                        NvmeCmd *cmd);
69788eea45cSKlaus Jensen 
69852581c71SMarkus Armbruster #endif /* HW_NVME_NVME_H */
699