aboutsummaryrefslogtreecommitdiff
path: root/hw/nvme/ns.c
diff options
context:
space:
mode:
authorNaveen Nagar <naveen.n1@samsung.com>2021-11-16 18:56:52 +0530
committerKlaus Jensen <k.jensen@samsung.com>2022-03-03 09:30:21 +0100
commit44219b6029fc52d5e967a963be91a9cf33f9f185 (patch)
treecbe9fe03c7cad144ed411a2a529d45b3921a4f21 /hw/nvme/ns.c
parentac0b34c58d0de09ce692af0a6c9a00a4eed0f3cd (diff)
downloadqemu-44219b6029fc52d5e967a963be91a9cf33f9f185.zip
qemu-44219b6029fc52d5e967a963be91a9cf33f9f185.tar.gz
qemu-44219b6029fc52d5e967a963be91a9cf33f9f185.tar.bz2
hw/nvme: 64-bit pi support
This adds support for one possible new protection information format introduced in TP4068 (and integrated in NVMe 2.0): the 64-bit CRC guard and 48-bit reference tag. This version does not support storage tags. Like the CRC16 support already present, this uses a software implementation of CRC64 (so it is naturally pretty slow). But its good enough for verification purposes. This may go nicely hand-in-hand with the support that Keith submitted for the Linux kernel[1]. [1]: https://lore.kernel.org/linux-nvme/20220126165214.GA1782352@dhcp-10-100-145-180.wdc.com/T/ Reviewed-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Naveen Nagar <naveen.n1@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
Diffstat (limited to 'hw/nvme/ns.c')
-rw-r--r--hw/nvme/ns.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/hw/nvme/ns.c b/hw/nvme/ns.c
index 8dfb551..8a3613d 100644
--- a/hw/nvme/ns.c
+++ b/hw/nvme/ns.c
@@ -58,6 +58,7 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
{
static uint64_t ns_count;
NvmeIdNs *id_ns = &ns->id_ns;
+ NvmeIdNsNvm *id_ns_nvm = &ns->id_ns_nvm;
uint8_t ds;
uint16_t ms;
int i;
@@ -101,6 +102,8 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
id_ns->dps |= NVME_ID_NS_DPS_FIRST_EIGHT;
}
+ ns->pif = ns->params.pif;
+
static const NvmeLBAF lbaf[16] = {
[0] = { .ds = 9 },
[1] = { .ds = 9, .ms = 8 },
@@ -133,7 +136,9 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
id_ns->flbas |= i;
+
lbaf_found:
+ id_ns_nvm->elbaf[i] = (ns->pif & 0x3) << 7;
id_ns->nlbaf = ns->nlbaf - 1;
nvme_ns_init_format(ns);
@@ -373,15 +378,36 @@ static void nvme_zoned_ns_shutdown(NvmeNamespace *ns)
static int nvme_ns_check_constraints(NvmeNamespace *ns, Error **errp)
{
+ unsigned int pi_size;
+
if (!ns->blkconf.blk) {
error_setg(errp, "block backend not configured");
return -1;
}
- if (ns->params.pi && ns->params.ms < 8) {
- error_setg(errp, "at least 8 bytes of metadata required to enable "
- "protection information");
- return -1;
+ if (ns->params.pi) {
+ if (ns->params.pi > NVME_ID_NS_DPS_TYPE_3) {
+ error_setg(errp, "invalid 'pi' value");
+ return -1;
+ }
+
+ switch (ns->params.pif) {
+ case NVME_PI_GUARD_16:
+ pi_size = 8;
+ break;
+ case NVME_PI_GUARD_64:
+ pi_size = 16;
+ break;
+ default:
+ error_setg(errp, "invalid 'pif'");
+ return -1;
+ }
+
+ if (ns->params.ms < pi_size) {
+ error_setg(errp, "at least %u bytes of metadata required to "
+ "enable protection information", pi_size);
+ return -1;
+ }
}
if (ns->params.nsid > NVME_MAX_NAMESPACES) {
@@ -593,6 +619,7 @@ static Property nvme_ns_props[] = {
DEFINE_PROP_UINT8("mset", NvmeNamespace, params.mset, 0),
DEFINE_PROP_UINT8("pi", NvmeNamespace, params.pi, 0),
DEFINE_PROP_UINT8("pil", NvmeNamespace, params.pil, 0),
+ DEFINE_PROP_UINT8("pif", NvmeNamespace, params.pif, 0),
DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128),
DEFINE_PROP_UINT32("mcl", NvmeNamespace, params.mcl, 128),
DEFINE_PROP_UINT8("msrc", NvmeNamespace, params.msrc, 127),