hw/nvme updates

Small set of fixes and some updates for the FDP support.
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEUigzqnXi3OaiR2bATeGvMW1PDekFAmSb/D4ACgkQTeGvMW1P
 DemziAf/eQfjnVr57A+Kglf8J15MCW0GiArbHCJfcl9vf0HPP/iY1c9V4cCZjTLG
 vkkkU6W+TFaYALGOVgAldHWC7OCpOi7GHrlqRJDuw86d2dyLDn/l+GQin/rVoocD
 fzF2gRVQU4x9qzmjRUikVhRzZbrB4F/AH6QQ8EV3wx2wrljyusItEGe53FEuCugx
 pwtKrG990188+UCT1ofr2JYhLq3OmYQi3o2fWgzMp9jP+NeROgKaevWG4UEhFonG
 CdeL9BMlSRAfrdR1gTvZpG2mFsrroeBCCjXcrKSwkAxBqpMJDSLvbGqoGJo6kDWm
 c9x82Zy2/wVuQaDk+atmcTF1+Pddgw==
 =//ks
 -----END PGP SIGNATURE-----

Merge tag 'nvme-next-pull-request' of https://gitlab.com/birkelund/qemu into staging

hw/nvme updates

Small set of fixes and some updates for the FDP support.

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEUigzqnXi3OaiR2bATeGvMW1PDekFAmSb/D4ACgkQTeGvMW1P
# DemziAf/eQfjnVr57A+Kglf8J15MCW0GiArbHCJfcl9vf0HPP/iY1c9V4cCZjTLG
# vkkkU6W+TFaYALGOVgAldHWC7OCpOi7GHrlqRJDuw86d2dyLDn/l+GQin/rVoocD
# fzF2gRVQU4x9qzmjRUikVhRzZbrB4F/AH6QQ8EV3wx2wrljyusItEGe53FEuCugx
# pwtKrG990188+UCT1ofr2JYhLq3OmYQi3o2fWgzMp9jP+NeROgKaevWG4UEhFonG
# CdeL9BMlSRAfrdR1gTvZpG2mFsrroeBCCjXcrKSwkAxBqpMJDSLvbGqoGJo6kDWm
# c9x82Zy2/wVuQaDk+atmcTF1+Pddgw==
# =//ks
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 28 Jun 2023 11:24:14 AM CEST
# gpg:                using RSA key 522833AA75E2DCE6A24766C04DE1AF316D4F0DE9
# gpg: Good signature from "Klaus Jensen <its@irrelevant.dk>" [unknown]
# gpg:                 aka "Klaus Jensen <k.jensen@samsung.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: DDCA 4D9C 9EF9 31CC 3468  4272 63D5 6FC5 E55D A838
#      Subkey fingerprint: 5228 33AA 75E2 DCE6 A247  66C0 4DE1 AF31 6D4F 0DE9

* tag 'nvme-next-pull-request' of https://gitlab.com/birkelund/qemu:
  docs: update hw/nvme documentation for TP4146
  hw/nvme: add placement handle list ranges
  hw/nvme: verify uniqueness of reclaim unit handle identifiers
  hw/nvme: fix verification of number of ruhis
  hw/nvme: check maximum copy length (MCL) for COPY
  hw/nvme: consider COPY command in nvme_aio_err
  hw/nvme: add comment for nvme-ns properties

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-06-28 11:44:12 +02:00
commit aa1048e33c
4 changed files with 117 additions and 15 deletions

View File

@ -212,6 +212,41 @@ The namespace may be configured with additional parameters
the minimum memory page size (CAP.MPSMIN). The default value (``0``)
has this property inherit the ``mdts`` value.
Flexible Data Placement
-----------------------
The device may be configured to support TP4146 ("Flexible Data Placement") by
configuring it (``fdp=on``) on the subsystem::
-device nvme-subsys,id=nvme-subsys-0,nqn=subsys0,fdp=on,fdp.nruh=16
The subsystem emulates a single Endurance Group, on which Flexible Data
Placement will be supported. Also note that the device emulation deviates
slightly from the specification, by always enabling the "FDP Mode" feature on
the controller if the subsystems is configured for Flexible Data Placement.
Enabling Flexible Data Placement on the subsyste enables the following
parameters:
``fdp.nrg`` (default: ``1``)
Set the number of Reclaim Groups.
``fdp.nruh`` (default: ``0``)
Set the number of Reclaim Unit Handles. This is a mandatory paramater and
must be non-zero.
``fdp.runs`` (default: ``96M``)
Set the Reclaim Unit Nominal Size. Defaults to 96 MiB.
Namespaces within this subsystem may requests Reclaim Unit Handles::
-device nvme-ns,drive=nvm-1,fdp.ruhs=RUHLIST
The ``RUHLIST`` is a semicolon separated list (i.e. ``0;1;2;3``) and may
include ranges (i.e. ``0;8-15``). If no reclaim unit handle list is specified,
the controller will assign the controller-specified reclaim unit handle to
placement handle identifier 0.
Metadata
--------
@ -320,4 +355,4 @@ controller are:
.. code-block:: console
echo 0000:01:00.1 > /sys/bus/pci/drivers/nvme/bind
echo 0000:01:00.1 > /sys/bus/pci/drivers/nvme/bind

View File

@ -43,7 +43,14 @@
* subsys=<subsys_id>
* -device nvme-ns,drive=<drive_id>,bus=<bus_name>,nsid=<nsid>,\
* zoned=<true|false[optional]>, \
* subsys=<subsys_id>,detached=<true|false[optional]>
* subsys=<subsys_id>,shared=<true|false[optional]>, \
* detached=<true|false[optional]>, \
* zoned.zone_size=<N[optional]>, \
* zoned.zone_capacity=<N[optional]>, \
* zoned.descr_ext_size=<N[optional]>, \
* zoned.max_active=<N[optional]>, \
* zoned.max_open=<N[optional]>, \
* zoned.cross_read=<true|false[optional]>
*
* Note cmb_size_mb denotes size of CMB in MB. CMB is assumed to be at
* offset 0 in BAR2 and supports only WDS, RDS and SQS for now. By default, the
@ -1748,6 +1755,7 @@ static void nvme_aio_err(NvmeRequest *req, int ret)
case NVME_CMD_WRITE:
case NVME_CMD_WRITE_ZEROES:
case NVME_CMD_ZONE_APPEND:
case NVME_CMD_COPY:
status = NVME_WRITE_FAULT;
break;
default:
@ -2847,6 +2855,25 @@ static void nvme_copy_source_range_parse(void *ranges, int idx, uint8_t format,
}
}
static inline uint16_t nvme_check_copy_mcl(NvmeNamespace *ns,
NvmeCopyAIOCB *iocb, uint16_t nr)
{
uint32_t copy_len = 0;
for (int idx = 0; idx < nr; idx++) {
uint32_t nlb;
nvme_copy_source_range_parse(iocb->ranges, idx, iocb->format, NULL,
&nlb, NULL, NULL, NULL);
copy_len += nlb + 1;
}
if (copy_len > ns->id_ns.mcl) {
return NVME_CMD_SIZE_LIMIT | NVME_DNR;
}
return NVME_SUCCESS;
}
static void nvme_copy_out_completed_cb(void *opaque, int ret)
{
NvmeCopyAIOCB *iocb = opaque;
@ -3159,6 +3186,11 @@ static uint16_t nvme_copy(NvmeCtrl *n, NvmeRequest *req)
}
}
status = nvme_check_copy_mcl(ns, iocb, nr);
if (status) {
goto invalid;
}
iocb->req = req;
iocb->ret = 0;
iocb->nr = nr;

View File

@ -400,8 +400,9 @@ static bool nvme_ns_init_fdp(NvmeNamespace *ns, Error **errp)
NvmeRuHandle *ruh;
uint8_t lbafi = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas);
g_autofree unsigned int *ruhids = NULL;
unsigned int *ruhid;
char *r, *p, *token;
unsigned int n, m, *ruhid;
const char *endptr, *token;
char *r, *p;
uint16_t *ph;
if (!ns->params.fdp.ruhs) {
@ -438,23 +439,55 @@ static bool nvme_ns_init_fdp(NvmeNamespace *ns, Error **errp)
/* parse the placement handle identifiers */
while ((token = qemu_strsep(&p, ";")) != NULL) {
ns->fdp.nphs += 1;
if (ns->fdp.nphs > NVME_FDP_MAXPIDS ||
ns->fdp.nphs == endgrp->fdp.nruh) {
error_setg(errp, "too many placement handles");
free(r);
return false;
}
if (qemu_strtoui(token, NULL, 0, ruhid++) < 0) {
if (qemu_strtoui(token, &endptr, 0, &n) < 0) {
error_setg(errp, "cannot parse reclaim unit handle identifier");
free(r);
return false;
}
m = n;
/* parse range */
if (*endptr == '-') {
token = endptr + 1;
if (qemu_strtoui(token, NULL, 0, &m) < 0) {
error_setg(errp, "cannot parse reclaim unit handle identifier");
free(r);
return false;
}
if (m < n) {
error_setg(errp, "invalid reclaim unit handle identifier range");
free(r);
return false;
}
}
for (; n <= m; n++) {
if (ns->fdp.nphs++ == endgrp->fdp.nruh) {
error_setg(errp, "too many placement handles");
free(r);
return false;
}
*ruhid++ = n;
}
}
free(r);
/* verify that the ruhids are unique */
for (unsigned int i = 0; i < ns->fdp.nphs; i++) {
for (unsigned int j = i + 1; j < ns->fdp.nphs; j++) {
if (ruhids[i] == ruhids[j]) {
error_setg(errp, "duplicate reclaim unit handle identifier: %u",
ruhids[i]);
return false;
}
}
}
ph = ns->fdp.phs = g_new(uint16_t, ns->fdp.nphs);
ruhid = ruhids;

View File

@ -158,8 +158,10 @@ static bool nvme_subsys_setup_fdp(NvmeSubsystem *subsys, Error **errp)
endgrp->fdp.nrg = subsys->params.fdp.nrg;
if (!subsys->params.fdp.nruh) {
error_setg(errp, "fdp.nruh must be non-zero");
if (!subsys->params.fdp.nruh ||
subsys->params.fdp.nruh > NVME_FDP_MAXPIDS) {
error_setg(errp, "fdp.nruh must be non-zero and less than %u",
NVME_FDP_MAXPIDS);
return false;
}