From: Klaus Birkelund <its@irrelevant.dk>
To: Beata Michalska <beata.michalska@linaro.org>
Cc: Kevin Wolf <kwolf@redhat.com>,
qemu-block@nongnu.org, qemu-devel@nongnu.org,
Max Reitz <mreitz@redhat.com>,
Paul Durrant <Paul.Durrant@citrix.com>,
Keith Busch <kbusch@kernel.org>
Subject: Re: [PATCH v2 13/20] nvme: refactor prp mapping
Date: Wed, 20 Nov 2019 10:39:14 +0100 [thread overview]
Message-ID: <20191120093914.GA1052314@apples.localdomain> (raw)
In-Reply-To: <CADSWDzs6mECPKv2qAojEF75Vxi1i5_2fkvDtjWkQU22F9a4a7g@mail.gmail.com>
On Tue, Nov 12, 2019 at 03:23:43PM +0000, Beata Michalska wrote:
> Hi Klaus,
>
> On Tue, 15 Oct 2019 at 11:57, Klaus Jensen <its@irrelevant.dk> wrote:
> >
> > Instead of handling both QSGs and IOVs in multiple places, simply use
> > QSGs everywhere by assuming that the request does not involve the
> > controller memory buffer (CMB). If the request is found to involve the
> > CMB, convert the QSG to an IOV and issue the I/O. The QSG is converted
> > to an IOV by the dma helpers anyway, so the CMB path is not unfairly
> > affected by this simplifying change.
> >
>
> Out of curiosity, in how many cases the SG list will have to
> be converted to IOV ? Does that justify creating the SG list in vain ?
>
You got me wondering. Only using QSGs does not really remove much
complexity, so I readded the direct use of IOVs for the CMB path. There
is no harm in that.
> > +static uint16_t nvme_map_prp(NvmeCtrl *n, QEMUSGList *qsg, uint64_t prp1,
> > + uint64_t prp2, uint32_t len, NvmeRequest *req)
> > {
> > hwaddr trans_len = n->page_size - (prp1 % n->page_size);
> > trans_len = MIN(len, trans_len);
> > int num_prps = (len >> n->page_bits) + 1;
> > + uint16_t status = NVME_SUCCESS;
> > + bool prp_list_in_cmb = false;
> > +
> > + trace_nvme_map_prp(req->cid, req->cmd.opcode, trans_len, len, prp1, prp2,
> > + num_prps);
> >
> > if (unlikely(!prp1)) {
> > trace_nvme_err_invalid_prp();
> > return NVME_INVALID_FIELD | NVME_DNR;
> > - } else if (n->cmbsz && prp1 >= n->ctrl_mem.addr &&
> > - prp1 < n->ctrl_mem.addr + int128_get64(n->ctrl_mem.size)) {
> > - qsg->nsg = 0;
> > - qemu_iovec_init(iov, num_prps);
> > - qemu_iovec_add(iov, (void *)&n->cmbuf[prp1 - n->ctrl_mem.addr], trans_len);
> > - } else {
> > - pci_dma_sglist_init(qsg, &n->parent_obj, num_prps);
> > - qemu_sglist_add(qsg, prp1, trans_len);
> > }
> > +
> > + if (nvme_addr_is_cmb(n, prp1)) {
> > + req->is_cmb = true;
> > + }
> > +
> This seems to be used here and within read/write functions which are calling
> this one. Maybe there is a nicer way to track that instead of passing
> the request
> from multiple places ?
>
Hmm. Whether or not the command reads/writes from the CMB is really only
something you can determine by looking at the PRPs (which is done in
nvme_map_prp), so I think this is the right way to track it. Or do you
have something else in mind?
> > + pci_dma_sglist_init(qsg, &n->parent_obj, num_prps);
> > + qemu_sglist_add(qsg, prp1, trans_len);
> > +
> > len -= trans_len;
> > if (len) {
> > if (unlikely(!prp2)) {
> > trace_nvme_err_invalid_prp2_missing();
> > + status = NVME_INVALID_FIELD | NVME_DNR;
> > goto unmap;
> > }
> > +
> > if (len > n->page_size) {
> > uint64_t prp_list[n->max_prp_ents];
> > uint32_t nents, prp_trans;
> > int i = 0;
> >
> > + if (nvme_addr_is_cmb(n, prp2)) {
> > + prp_list_in_cmb = true;
> > + }
> > +
> > nents = (len + n->page_size - 1) >> n->page_bits;
> > prp_trans = MIN(n->max_prp_ents, nents) * sizeof(uint64_t);
> > - nvme_addr_read(n, prp2, (void *)prp_list, prp_trans);
> > + nvme_addr_read(n, prp2, (void *) prp_list, prp_trans);
> > while (len != 0) {
> > + bool addr_is_cmb;
> > uint64_t prp_ent = le64_to_cpu(prp_list[i]);
> >
> > if (i == n->max_prp_ents - 1 && len > n->page_size) {
> > if (unlikely(!prp_ent || prp_ent & (n->page_size - 1))) {
> > trace_nvme_err_invalid_prplist_ent(prp_ent);
> > + status = NVME_INVALID_FIELD | NVME_DNR;
> > + goto unmap;
> > + }
> > +
> > + addr_is_cmb = nvme_addr_is_cmb(n, prp_ent);
> > + if ((prp_list_in_cmb && !addr_is_cmb) ||
> > + (!prp_list_in_cmb && addr_is_cmb)) {
>
> Minor: Same condition (based on different vars) is being used in
> multiple places. Might be worth to move it outside and just pass in
> the needed values.
>
I'm really not sure what I was smoking when writing those conditions.
It's just `var != nvme_addr_is_cmb(n, prp_ent)`. I fixed that. No need
to pull it out I think.
> > static uint16_t nvme_dma_write_prp(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
> > - uint64_t prp1, uint64_t prp2)
> > + uint64_t prp1, uint64_t prp2, NvmeRequest *req)
> > {
> > QEMUSGList qsg;
> > - QEMUIOVector iov;
> > uint16_t status = NVME_SUCCESS;
> >
> > - if (nvme_map_prp(&qsg, &iov, prp1, prp2, len, n)) {
> > - return NVME_INVALID_FIELD | NVME_DNR;
> > + status = nvme_map_prp(n, &qsg, prp1, prp2, len, req);
> > + if (status) {
> > + return status;
> > }
> > - if (qsg.nsg > 0) {
> > - if (dma_buf_write(ptr, len, &qsg)) {
> > - status = NVME_INVALID_FIELD | NVME_DNR;
> > - }
> > - qemu_sglist_destroy(&qsg);
> > - } else {
> > - if (qemu_iovec_to_buf(&iov, 0, ptr, len) != len) {
> > +
> > + if (req->is_cmb) {
> > + QEMUIOVector iov;
> > +
> > + qemu_iovec_init(&iov, qsg.nsg);
> > + dma_to_cmb(n, &qsg, &iov);
> > +
> > + if (unlikely(qemu_iovec_to_buf(&iov, 0, ptr, len) != len)) {
> > + trace_nvme_err_invalid_dma();
> > status = NVME_INVALID_FIELD | NVME_DNR;
> > }
> > +
> > qemu_iovec_destroy(&iov);
> > +
> Aren't we missing the sglist cleanup here ?
> (goto as in nvme_dma_read_prp)
>
> Aside: both nvme_write_prp and nvme_read_prp seem to differ only
> with the final call to either dma or qemu_ioves calls.
> Might be worth to unify it and move it to a single function with additional
> parameter that will determine the type of the transaction.
>
True. I have combined them into a single nvme_dma_prp function.
> > +static void nvme_init_req(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
> > +{
> > + memset(&req->cqe, 0, sizeof(req->cqe));
> > + req->cqe.cid = cmd->cid;
> > + req->cid = le16_to_cpu(cmd->cid);
> > +
> > + memcpy(&req->cmd, cmd, sizeof(NvmeCmd));
> > + req->status = NVME_SUCCESS;
> > + req->is_cmb = false;
> > + req->is_write = false;
>
> What is the use case for this one ?
> It does not seem to be referenced in this patch.
>
That crept in there by mistake. I have removed it.
next prev parent reply other threads:[~2019-11-20 9:41 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-15 10:38 [PATCH v2 00/20] nvme: support NVMe v1.3d, SGLs and multiple namespaces Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 01/20] nvme: remove superfluous breaks Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 02/20] nvme: move device parameters to separate struct Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 03/20] nvme: add missing fields in the identify controller data structure Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 04/20] nvme: populate the mandatory subnqn and ver fields Klaus Jensen
2019-11-12 15:04 ` Beata Michalska
2019-11-13 6:16 ` Klaus Birkelund
2019-10-15 10:38 ` [PATCH v2 05/20] nvme: allow completion queues in the cmb Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 06/20] nvme: add support for the abort command Klaus Jensen
2019-11-12 15:04 ` Beata Michalska
2019-11-13 6:12 ` Klaus Birkelund
2019-11-15 11:56 ` Beata Michalska
2019-11-18 8:49 ` Klaus Birkelund
2019-10-15 10:38 ` [PATCH v2 07/20] nvme: refactor device realization Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 08/20] nvme: add support for the get log page command Klaus Jensen
2019-11-12 15:04 ` Beata Michalska
2019-11-19 20:01 ` Klaus Birkelund
2019-10-15 10:38 ` [PATCH v2 09/20] nvme: add support for the asynchronous event request command Klaus Jensen
2019-11-12 15:04 ` Beata Michalska
2019-11-19 19:51 ` Klaus Birkelund
2019-11-25 12:44 ` Beata Michalska
2019-10-15 10:38 ` [PATCH v2 10/20] nvme: add logging to error information log page Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 11/20] nvme: add missing mandatory features Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 12/20] nvme: bump supported specification version to 1.3 Klaus Jensen
2019-11-12 15:05 ` Beata Michalska
2019-11-18 9:48 ` Klaus Birkelund
2019-11-25 12:13 ` Beata Michalska
2019-11-26 8:40 ` Klaus Birkelund
2019-10-15 10:38 ` [PATCH v2 13/20] nvme: refactor prp mapping Klaus Jensen
2019-11-12 15:23 ` Beata Michalska
2019-11-20 9:39 ` Klaus Birkelund [this message]
2019-11-25 13:15 ` Beata Michalska
2019-10-15 10:38 ` [PATCH v2 14/20] nvme: allow multiple aios per command Klaus Jensen
2019-11-12 15:25 ` Beata Michalska
2019-11-21 11:57 ` Klaus Birkelund
2019-11-25 13:59 ` Beata Michalska
2019-10-15 10:38 ` [PATCH v2 15/20] nvme: add support for scatter gather lists Klaus Jensen
2019-11-12 15:25 ` Beata Michalska
2019-11-25 6:21 ` Klaus Birkelund
2019-11-25 14:10 ` Beata Michalska
2019-11-26 8:34 ` Klaus Birkelund
2019-10-15 10:38 ` [PATCH v2 16/20] nvme: support multiple namespaces Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 17/20] nvme: bump controller pci device id Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 18/20] nvme: remove redundant NvmeCmd pointer parameter Klaus Jensen
2019-10-15 10:38 ` [PATCH v2 19/20] nvme: make lba data size configurable Klaus Jensen
2019-11-12 15:24 ` Beata Michalska
2019-11-13 7:13 ` Klaus Birkelund
2019-10-15 10:39 ` [PATCH v2 20/20] nvme: handle dma errors Klaus Jensen
2019-10-15 17:19 ` [PATCH v2 00/20] nvme: support NVMe v1.3d, SGLs and multiple namespaces no-reply
2019-10-15 17:26 ` no-reply
2019-10-16 6:29 ` Fam Zheng
2019-10-28 6:09 ` Klaus Birkelund
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=20191120093914.GA1052314@apples.localdomain \
--to=its@irrelevant.dk \
--cc=Paul.Durrant@citrix.com \
--cc=beata.michalska@linaro.org \
--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).