qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Maxim Levitsky <mlevitsk@redhat.com>
To: Klaus Birkelund Jensen <its@irrelevant.dk>
Cc: Kevin Wolf <kwolf@redhat.com>,
	Beata Michalska <beata.michalska@linaro.org>,
	qemu-block@nongnu.org, qemu-devel@nongnu.org,
	Max Reitz <mreitz@redhat.com>, Keith Busch <kbusch@kernel.org>,
	Javier Gonzalez <javier.gonz@samsung.com>
Subject: Re: [PATCH v6 36/42] nvme: add support for scatter gather lists
Date: Tue, 31 Mar 2020 11:51:18 +0300	[thread overview]
Message-ID: <586ae8bcadfc5ae382d8fff7c28fd8bcfdc41862.camel@redhat.com> (raw)
In-Reply-To: <20200331054753.dqxttb7rgxcwok5d@apples.localdomain>

On Tue, 2020-03-31 at 07:48 +0200, Klaus Birkelund Jensen wrote:
> On Mar 25 12:58, Maxim Levitsky wrote:
> > On Mon, 2020-03-16 at 07:29 -0700, Klaus Jensen wrote:
> > > From: Klaus Jensen <k.jensen@samsung.com>
> > > 
> > > For now, support the Data Block, Segment and Last Segment descriptor
> > > types.
> > > 
> > > See NVM Express 1.3d, Section 4.4 ("Scatter Gather List (SGL)").
> > > 
> > > Signed-off-by: Klaus Jensen <klaus.jensen@cnexlabs.com>
> > > Acked-by: Keith Busch <kbusch@kernel.org>
> > > ---
> > >  hw/block/nvme.c       | 310 +++++++++++++++++++++++++++++++++++-------
> > >  hw/block/trace-events |   4 +
> > >  2 files changed, 262 insertions(+), 52 deletions(-)
> > > 
> > > diff --git a/hw/block/nvme.c b/hw/block/nvme.c
> > > index 49d323566393..b89b96990f52 100644
> > > --- a/hw/block/nvme.c
> > > +++ b/hw/block/nvme.c
> > > @@ -76,7 +76,12 @@ static inline bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr)
> > >  
> > >  static int nvme_addr_read(NvmeCtrl *n, hwaddr addr, void *buf, int size)
> > >  {
> > > -    if (n->bar.cmbsz && nvme_addr_is_cmb(n, addr)) {
> > > +    hwaddr hi = addr + size;
> > > +    if (hi < addr) {
> > > +        return 1;
> > > +    }
> > > +
> > > +    if (n->bar.cmbsz && nvme_addr_is_cmb(n, addr) && nvme_addr_is_cmb(n, hi)) {
> > 
> > I would suggest to split this into a separate patch as well, since this contains not just one but 2 bugfixes
> > for this function and they are not related to sg lists.
> > Or at least move this to 'nvme: refactor nvme_addr_read' and rename this patch
> > to something like 'nvme: fix and refactor nvme_addr_read'
> > 
> 
> I've split it into a patch.
> 
> > 
> > >          memcpy(buf, nvme_addr_to_cmb(n, addr), size);
> > >          return 0;
> > >      }
> > > @@ -328,13 +333,242 @@ unmap:
> > >      return status;
> > >  }
> > >  
> > > -static uint16_t nvme_dma_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
> > > -                             uint64_t prp1, uint64_t prp2, DMADirection dir,
> > > +static uint16_t nvme_map_sgl_data(NvmeCtrl *n, QEMUSGList *qsg,
> > > +                                  QEMUIOVector *iov,
> > > +                                  NvmeSglDescriptor *segment, uint64_t nsgld,
> > > +                                  size_t *len, NvmeRequest *req)
> > > +{
> > > +    dma_addr_t addr, trans_len;
> > > +    uint32_t blk_len;
> > > +    uint16_t status;
> > > +
> > > +    for (int i = 0; i < nsgld; i++) {
> > > +        uint8_t type = NVME_SGL_TYPE(segment[i].type);
> > > +
> > > +        if (type != NVME_SGL_DESCR_TYPE_DATA_BLOCK) {
> > > +            switch (type) {
> > > +            case NVME_SGL_DESCR_TYPE_BIT_BUCKET:
> > > +            case NVME_SGL_DESCR_TYPE_KEYED_DATA_BLOCK:
> > > +                return NVME_SGL_DESCR_TYPE_INVALID | NVME_DNR;
> > > +            default:
> > 
> > To be honest I don't like that 'default'
> > I would explicitly state which segment types remain 
> > (I think segment list and last segment list, and various reserved types)
> > In fact for the reserved types you probably also want to return NVME_SGL_DESCR_TYPE_INVALID)
> > 
> 
> I "negated" the logic which I think is more readable. I still really
> want to keep the default, for instance, nvme v1.4 adds a new type that
> we do not support (the Transport SGL Data Block descriptor).
OK, I'll take a look a that in the next version of the patches.

> 
> > Also this function as well really begs to have a description prior to it,
> > something like 'map a sg list section, assuming that it only contains SGL data descriptions,
> > caller has to ensure this'.
> > 
> 
> Done.
Thanks a lot!
> 
> > 
> > > +                return NVME_INVALID_NUM_SGL_DESCRS | NVME_DNR;
> > > +            }
> > > +        }
> > > +
> > > +        if (*len == 0) {
> > > +            uint16_t sgls = le16_to_cpu(n->id_ctrl.sgls);
> > 
> > Nitpick: I would add a small comment here as well describiing
> > what this does (We reach this point if sg list covers more that that
> > was specified in the commmand, and the NVME_CTRL_SGLS_EXCESS_LENGTH controller
> > capability indicates that we support just throwing the extra data away)
> > 
> 
> Adding a comment. It's the other way around. The size as indicated by
> NLB (or whatever depending on the command) is the "authoritative" souce
> of information for the size of the payload. We will never accept an SGL
> that is too short such that we lose or throw away data, but we might
> accept ignoring parts of the SGL.
Yes, that is what I meant. Thanks!

> 
> > > +            if (sgls & NVME_CTRL_SGLS_EXCESS_LENGTH) {
> > > +                break;
> > > +            }
> > > +
> > > +            trace_nvme_dev_err_invalid_sgl_excess_length(nvme_cid(req));
> > > +            return NVME_DATA_SGL_LEN_INVALID | NVME_DNR;
> > > +        }
> > > +
> > > +        addr = le64_to_cpu(segment[i].addr);
> > > +        blk_len = le32_to_cpu(segment[i].len);
> > > +
> > > +        if (!blk_len) {
> > > +            continue;
> > > +        }
> > > +
> > > +        if (UINT64_MAX - addr < blk_len) {
> > > +            return NVME_DATA_SGL_LEN_INVALID | NVME_DNR;
> > > +        }
> > 
> > Good!
> > > +
> > > +        trans_len = MIN(*len, blk_len);
> > > +
> > > +        status = nvme_map_addr(n, qsg, iov, addr, trans_len);
> > > +        if (status) {
> > > +            return status;
> > > +        }
> > > +
> > > +        *len -= trans_len;
> > > +    }
> > > +
> > > +    return NVME_SUCCESS;
> > > +}
> > > +
> > > +static uint16_t nvme_map_sgl(NvmeCtrl *n, QEMUSGList *qsg, QEMUIOVector *iov,
> > > +                             NvmeSglDescriptor sgl, size_t len,
> > >                               NvmeRequest *req)
> > > +{
> > > +    /*
> > > +     * Read the segment in chunks of 256 descriptors (one 4k page) to avoid
> > > +     * dynamically allocating a potentially large SGL. The spec allows the SGL
> > > +     * to be larger than the command transfer size, so it is not bounded by
> > > +     * MDTS.
> > > +     */
> > 
> > Now this is a very good comment!
> > 
> > However I don't fully understand the note about the SGL. I assume that you mean
> > that the data that SGL covers still should be less that MDTS, but the actual SGL chain,
> > if assembled really in inefficient way (like 1 byte per each data descriptor) might be larger.
> > 
> 
> Exactly. I'll rephrase.
Thanks!
> 
> > 
> > > +    const int SEG_CHUNK_SIZE = 256;
> > > +
> > > +    NvmeSglDescriptor segment[SEG_CHUNK_SIZE], *sgld, *last_sgld;
> > > +    uint64_t nsgld;
> > > +    uint32_t seg_len;
> > > +    uint16_t status;
> > > +    bool sgl_in_cmb = false;
> > > +    hwaddr addr;
> > > +    int ret;
> > > +
> > > +    sgld = &sgl;
> > > +    addr = le64_to_cpu(sgl.addr);
> > > +
> > > +    trace_nvme_dev_map_sgl(nvme_cid(req), NVME_SGL_TYPE(sgl.type), req->nlb,
> > > +                           len);
> > > +
> > > +    /*
> > > +     * If the entire transfer can be described with a single data block it can
> > > +     * be mapped directly.
> > > +     */
> > > +    if (NVME_SGL_TYPE(sgl.type) == NVME_SGL_DESCR_TYPE_DATA_BLOCK) {
> > > +        status = nvme_map_sgl_data(n, qsg, iov, sgld, 1, &len, req);
> > > +        if (status) {
> > > +            goto unmap;
> > > +        }
> > > +
> > > +        goto out;
> > > +    }
> > > +
> > > +    /*
> > > +     * If the segment is located in the CMB, the submission queue of the
> > > +     * request must also reside there.
> > > +     */
> > > +    if (nvme_addr_is_cmb(n, addr)) {
> > > +        if (!nvme_addr_is_cmb(n, req->sq->dma_addr)) {
> > > +            return NVME_INVALID_USE_OF_CMB | NVME_DNR;
> > > +        }
> > > +
> > > +        sgl_in_cmb = true;
> > > +    }
> > > +
> > > +    for (;;) {
> > > +        seg_len = le32_to_cpu(sgld->len);
> > > +
> > > +        if (!seg_len || seg_len & 0xf) {
> > > +            return NVME_INVALID_SGL_SEG_DESCR | NVME_DNR;
> > > +        }
> > 
> > It might be worth noting here that we are dealing with sgl (last) segment descriptor
> > and its length indeed must be non zero and multiple of 16.
> > Otherwise I confused this for a moment with the alignment requirements on the data itsel.
> > 
> 
> Done.
Thanks as well!
> 
> > 
> > Best regards,
> > 	Maxim Levitsky
> > 
> > 
> > 
> > 
> > 
> 

Best regards,
	Maxim Levitsky




  reply	other threads:[~2020-03-31  8:52 UTC|newest]

Thread overview: 121+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-16 14:28 [PATCH v6 00/42] nvme: support NVMe v1.3d, SGLs and multiple namespaces Klaus Jensen
2020-03-16 14:28 ` [PATCH v6 01/42] nvme: rename trace events to nvme_dev Klaus Jensen
2020-03-25 10:36   ` Maxim Levitsky
2020-03-31  5:38     ` Klaus Birkelund Jensen
2020-03-16 14:28 ` [PATCH v6 02/42] nvme: remove superfluous breaks Klaus Jensen
2020-03-16 14:28 ` [PATCH v6 03/42] nvme: move device parameters to separate struct Klaus Jensen
2020-03-25 10:36   ` Maxim Levitsky
2020-03-16 14:28 ` [PATCH v6 04/42] nvme: bump spec data structures to v1.3 Klaus Jensen
2020-03-25 10:37   ` Maxim Levitsky
2020-03-31  5:38     ` Klaus Birkelund Jensen
2020-03-31 10:43       ` Maxim Levitsky
2020-03-16 14:28 ` [PATCH v6 05/42] nvme: use constant for identify data size Klaus Jensen
2020-03-25 10:37   ` Maxim Levitsky
2020-03-31  5:38     ` Klaus Birkelund Jensen
2020-03-16 14:28 ` [PATCH v6 06/42] nvme: add identify cns values in header Klaus Jensen
2020-03-25 10:37   ` Maxim Levitsky
2020-03-31  5:39     ` Klaus Birkelund Jensen
2020-03-16 14:28 ` [PATCH v6 07/42] nvme: refactor nvme_addr_read Klaus Jensen
2020-03-25 10:38   ` Maxim Levitsky
2020-03-31  5:39     ` Klaus Birkelund Jensen
2020-03-31 10:41       ` Maxim Levitsky
2020-03-31 12:48         ` Klaus Birkelund Jensen
2020-03-31 14:46           ` Maxim Levitsky
2020-03-16 14:28 ` [PATCH v6 08/42] nvme: add support for the abort command Klaus Jensen
2020-03-25 10:38   ` Maxim Levitsky
2020-03-16 14:28 ` [PATCH v6 09/42] nvme: add max_ioqpairs device parameter Klaus Jensen
2020-03-25 10:39   ` Maxim Levitsky
2020-03-31  5:40     ` Klaus Birkelund Jensen
2020-03-31  9:48       ` Maxim Levitsky
2020-03-16 14:28 ` [PATCH v6 10/42] nvme: refactor device realization Klaus Jensen
2020-03-25 10:40   ` Maxim Levitsky
2020-03-31  5:40     ` Klaus Birkelund Jensen
2020-03-16 14:28 ` [PATCH v6 11/42] nvme: add temperature threshold feature Klaus Jensen
2020-03-25 10:40   ` Maxim Levitsky
2020-03-31  5:40     ` Klaus Birkelund Jensen
2020-03-31  9:46       ` Maxim Levitsky
2020-03-16 14:28 ` [PATCH v6 12/42] nvme: add support for the get log page command Klaus Jensen
2020-03-25 10:40   ` Maxim Levitsky
2020-03-31  5:41     ` Klaus Birkelund Jensen
2020-03-31  9:45       ` Maxim Levitsky
2020-03-31 12:49         ` Klaus Birkelund Jensen
2020-03-31 14:47           ` Maxim Levitsky
2020-03-16 14:28 ` [PATCH v6 13/42] nvme: add support for the asynchronous event request command Klaus Jensen
2020-03-25 10:41   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 14/42] nvme: add missing mandatory features Klaus Jensen
2020-03-25 10:41   ` Maxim Levitsky
2020-03-31  5:41     ` Klaus Birkelund Jensen
2020-03-31  9:39       ` Maxim Levitsky
2020-04-08 11:28         ` Klaus Birkelund Jensen
2020-03-16 14:29 ` [PATCH v6 15/42] nvme: additional tracing Klaus Jensen
2020-03-25 10:42   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 16/42] nvme: make sure ncqr and nsqr is valid Klaus Jensen
2020-03-25 10:42   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 17/42] nvme: add log specific field to trace events Klaus Jensen
2020-03-25 10:43   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 18/42] nvme: support identify namespace descriptor list Klaus Jensen
2020-03-25 10:43   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 19/42] nvme: enforce valid queue creation sequence Klaus Jensen
2020-03-25 10:43   ` Maxim Levitsky
2020-03-31  5:41     ` Klaus Birkelund Jensen
2020-03-31  9:31       ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 20/42] nvme: provide the mandatory subnqn field Klaus Jensen
2020-03-25 10:43   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 21/42] nvme: bump supported version to v1.3 Klaus Jensen
2020-03-25 10:44   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 22/42] nvme: memset preallocated requests structures Klaus Jensen
2020-03-25 10:44   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 23/42] nvme: add mapping helpers Klaus Jensen
2020-03-25 10:45   ` Maxim Levitsky
2020-03-31  5:44     ` Klaus Birkelund Jensen
2020-03-31  9:30       ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 24/42] nvme: remove redundant has_sg member Klaus Jensen
2020-03-25 10:45   ` Maxim Levitsky
2020-03-31  5:44     ` Klaus Birkelund Jensen
2020-03-31  9:25       ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 25/42] nvme: refactor dma read/write Klaus Jensen
2020-03-25 10:46   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 26/42] nvme: pass request along for tracing Klaus Jensen
2020-03-25 10:55   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 27/42] nvme: add request mapping helper Klaus Jensen
2020-03-25 10:56   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 28/42] nvme: verify validity of prp lists in the cmb Klaus Jensen
2020-03-25 10:56   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 29/42] nvme: refactor request bounds checking Klaus Jensen
2020-03-25 10:56   ` Maxim Levitsky
2020-03-31  5:44     ` Klaus Birkelund Jensen
2020-03-31  9:23       ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 30/42] nvme: add check for mdts Klaus Jensen
2020-03-25 10:57   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 31/42] nvme: add check for prinfo Klaus Jensen
2020-03-25 10:57   ` Maxim Levitsky
2020-03-31  5:45     ` Klaus Birkelund Jensen
2020-03-31  9:17       ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 32/42] nvme: allow multiple aios per command Klaus Jensen
2020-03-25 10:57   ` Maxim Levitsky
2020-03-31  5:47     ` Klaus Birkelund Jensen
2020-03-31  9:10       ` Maxim Levitsky
2020-04-08 15:02         ` Klaus Birkelund Jensen
2020-03-16 14:29 ` [PATCH v6 33/42] nvme: use preallocated qsg/iov in nvme_dma_prp Klaus Jensen
2020-03-25 10:58   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 34/42] pci: pass along the return value of dma_memory_rw Klaus Jensen
2020-03-16 14:29 ` [PATCH v6 35/42] nvme: handle dma errors Klaus Jensen
2020-03-25 10:58   ` Maxim Levitsky
2020-03-31  5:47     ` Klaus Birkelund Jensen
2020-03-16 14:29 ` [PATCH v6 36/42] nvme: add support for scatter gather lists Klaus Jensen
2020-03-25 10:58   ` Maxim Levitsky
2020-03-31  5:48     ` Klaus Birkelund Jensen
2020-03-31  8:51       ` Maxim Levitsky [this message]
2020-03-16 14:29 ` [PATCH v6 37/42] nvme: refactor identify active namespace id list Klaus Jensen
2020-03-25 10:58   ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 38/42] nvme: support multiple namespaces Klaus Jensen
2020-03-25 10:59   ` Maxim Levitsky
2020-03-31  5:48     ` Klaus Birkelund Jensen
2020-03-31  8:47       ` Maxim Levitsky
2020-03-16 14:29 ` [PATCH v6 39/42] pci: allocate pci id for nvme Klaus Jensen
2020-03-16 14:29 ` [PATCH v6 40/42] nvme: change controller pci id Klaus Jensen
2020-03-16 14:29 ` [PATCH v6 41/42] nvme: remove redundant NvmeCmd pointer parameter Klaus Jensen
2020-03-16 14:29 ` [PATCH v6 42/42] nvme: make lba data size configurable Klaus Jensen
2020-03-25 10:59   ` Maxim Levitsky
2020-03-16 19:30 ` [PATCH v6 00/42] nvme: support NVMe v1.3d, SGLs and multiple namespaces no-reply
2020-03-25 10:35 ` Maxim Levitsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=586ae8bcadfc5ae382d8fff7c28fd8bcfdc41862.camel@redhat.com \
    --to=mlevitsk@redhat.com \
    --cc=beata.michalska@linaro.org \
    --cc=its@irrelevant.dk \
    --cc=javier.gonz@samsung.com \
    --cc=kbusch@kernel.org \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).