summaryrefslogtreecommitdiffstats
path: root/hw/block/nvme.h
diff options
context:
space:
mode:
authorKlaus Jensen2019-06-26 08:51:06 +0200
committerKlaus Jensen2020-10-27 07:24:47 +0100
commit7f0f1acedf159d00684d495d7a14d52220c1d16b (patch)
tree1dc8557a7ebdf56c5f664b0898b3ab8d40a6ed3a /hw/block/nvme.h
parenthw/block/nvme: refactor identify active namespace id list (diff)
downloadqemu-7f0f1acedf159d00684d495d7a14d52220c1d16b.tar.gz
qemu-7f0f1acedf159d00684d495d7a14d52220c1d16b.tar.xz
qemu-7f0f1acedf159d00684d495d7a14d52220c1d16b.zip
hw/block/nvme: support multiple namespaces
This adds support for multiple namespaces by introducing a new 'nvme-ns' device model. The nvme device creates a bus named from the device name ('id'). The nvme-ns devices then connect to this and registers themselves with the nvme device. This changes how an nvme device is created. Example with two namespaces: -drive file=nvme0n1.img,if=none,id=disk1 -drive file=nvme0n2.img,if=none,id=disk2 -device nvme,serial=deadbeef,id=nvme0 -device nvme-ns,drive=disk1,bus=nvme0,nsid=1 -device nvme-ns,drive=disk2,bus=nvme0,nsid=2 The drive property is kept on the nvme device to keep the change backward compatible, but the property is now optional. Specifying a drive for the nvme device will always create the namespace with nsid 1. Signed-off-by: Klaus Jensen <k.jensen@samsung.com> Reviewed-by: Keith Busch <kbusch@kernel.org> Reviewed-by: Minwoo Im <minwoo.im.dev@gmail.com>
Diffstat (limited to 'hw/block/nvme.h')
-rw-r--r--hw/block/nvme.h46
1 files changed, 21 insertions, 25 deletions
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index f355eccb32..d96ec15cdf 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -2,6 +2,9 @@
#define HW_NVME_H
#include "block/nvme.h"
+#include "nvme-ns.h"
+
+#define NVME_MAX_NAMESPACES 256
typedef struct NvmeParams {
char *serial;
@@ -90,26 +93,12 @@ typedef struct NvmeCQueue {
QTAILQ_HEAD(, NvmeRequest) req_list;
} NvmeCQueue;
-typedef struct NvmeNamespace {
- NvmeIdNs id_ns;
-} NvmeNamespace;
-
-static inline NvmeLBAF *nvme_ns_lbaf(NvmeNamespace *ns)
-{
- NvmeIdNs *id_ns = &ns->id_ns;
- return &id_ns->lbaf[NVME_ID_NS_FLBAS_INDEX(id_ns->flbas)];
-}
-
-static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns)
-{
- return nvme_ns_lbaf(ns)->ds;
-}
+#define TYPE_NVME_BUS "nvme-bus"
+#define NVME_BUS(obj) OBJECT_CHECK(NvmeBus, (obj), TYPE_NVME_BUS)
-/* convert an LBA to the equivalent in bytes */
-static inline size_t nvme_l2b(NvmeNamespace *ns, uint64_t lba)
-{
- return lba << nvme_ns_lbads(ns);
-}
+typedef struct NvmeBus {
+ BusState parent_bus;
+} NvmeBus;
#define TYPE_NVME "nvme"
#define NVME(obj) \
@@ -121,6 +110,7 @@ typedef struct NvmeFeatureVal {
uint16_t temp_thresh_low;
};
uint32_t async_config;
+ uint32_t vwc;
} NvmeFeatureVal;
typedef struct NvmeCtrl {
@@ -128,8 +118,9 @@ typedef struct NvmeCtrl {
MemoryRegion iomem;
MemoryRegion ctrl_mem;
NvmeBar bar;
- BlockConf conf;
NvmeParams params;
+ NvmeBus bus;
+ BlockConf conf;
bool qs_created;
uint32_t page_size;
@@ -140,7 +131,6 @@ typedef struct NvmeCtrl {
uint32_t reg_size;
uint32_t num_namespaces;
uint32_t max_q_ents;
- uint64_t ns_size;
uint8_t outstanding_aers;
uint8_t *cmbuf;
uint32_t irq_status;
@@ -156,7 +146,8 @@ typedef struct NvmeCtrl {
QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue;
int aer_queued;
- NvmeNamespace *namespaces;
+ NvmeNamespace namespace;
+ NvmeNamespace *namespaces[NVME_MAX_NAMESPACES];
NvmeSQueue **sq;
NvmeCQueue **cq;
NvmeSQueue admin_sq;
@@ -165,10 +156,13 @@ typedef struct NvmeCtrl {
NvmeFeatureVal features;
} NvmeCtrl;
-/* calculate the number of LBAs that the namespace can accomodate */
-static inline uint64_t nvme_ns_nlbas(NvmeCtrl *n, NvmeNamespace *ns)
+static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
{
- return n->ns_size >> nvme_ns_lbads(ns);
+ if (!nsid || nsid > n->num_namespaces) {
+ return NULL;
+ }
+
+ return n->namespaces[nsid - 1];
}
static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
@@ -185,4 +179,6 @@ static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req)
return sq->ctrl;
}
+int nvme_register_namespace(NvmeCtrl *n, NvmeNamespace *ns, Error **errp);
+
#endif /* HW_NVME_H */