From: Jonathan Cameron via <qemu-devel@nongnu.org>
To: Klaus Jensen <its@irrelevant.dk>
Cc: qemu-devel@nongnu.org, "Corey Minyard" <cminyard@mvista.com>,
"Keith Busch" <kbusch@kernel.org>,
"Jason Wang" <jasowang@redhat.com>,
"Lior Weintraub" <liorw@pliops.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Jeremy Kerr" <jk@codeconstruct.com.au>,
qemu-arm@nongnu.org, "Matt Johnston" <matt@codeconstruct.com.au>,
"Peter Delevoryas" <peter@pjd.dev>,
qemu-block@nongnu.org, "Cédric Le Goater" <clg@kaod.org>,
"Klaus Jensen" <k.jensen@samsung.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
gost.dev@samsung.com
Subject: Re: [PATCH v3 3/3] hw/nvme: add nvme management interface model
Date: Wed, 31 May 2023 16:39:57 +0100 [thread overview]
Message-ID: <20230531163957.0000494e@Huawei.com> (raw)
In-Reply-To: <20230531114744.9946-4-its@irrelevant.dk>
On Wed, 31 May 2023 13:47:44 +0200
Klaus Jensen <its@irrelevant.dk> wrote:
> From: Klaus Jensen <k.jensen@samsung.com>
>
> Add the 'nmi-i2c' device that emulates an NVMe Management Interface
> controller.
>
> Initial support is very basic (Read NMI DS, Configuration Get).
>
> This is based on previously posted code by Padmakar Kalghatgi, Arun
> Kumar Agasar and Saurav Kumar.
>
> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
A few comments inline - I dug into the specs this time so some
new questions.
Jonathan
> diff --git a/hw/nvme/nmi-i2c.c b/hw/nvme/nmi-i2c.c
> new file mode 100644
> index 000000000000..38e43e48fa51
> --- /dev/null
> +++ b/hw/nvme/nmi-i2c.c
> @@ -0,0 +1,367 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + * SPDX-FileCopyrightText: Copyright (c) 2022 Samsung Electronics Co., Ltd.
Update to 2023?
> +typedef struct NMIRequest {
> + uint8_t opc;
> + uint8_t rsvd1[3];
> + uint32_t dw0;
> + uint32_t dw1;
> + uint32_t mic;
> +} NMIRequest;
> +
> +typedef struct NMIResponse {
> + uint8_t status;
> + uint8_t response[3];
> + uint8_t payload[]; /* includes the Message Integrity Check */
> +} NMIResponse;
Not used.
> +
> +typedef enum NMIReadDSType {
> + NMI_CMD_READ_NMI_DS_SUBSYSTEM = 0x0,
> + NMI_CMD_READ_NMI_DS_PORTS = 0x1,
> + NMI_CMD_READ_NMI_DS_CTRL_LIST = 0x2,
> + NMI_CMD_READ_NMI_DS_CTRL_INFO = 0x3,
> + NMI_CMD_READ_NMI_DS_CMD_SUPPORT = 0x4,
> + NMI_CMD_READ_NMI_DS_MEB_CMD_SUPPORT = 0x5,
> +} NMIReadDSType;
> +
> +static void nmi_set_parameter_error(NMIDevice *nmi, uint8_t bit, uint16_t byte)
> +{
> + nmi->scratch[nmi->pos++] = 0x4;
> + nmi->scratch[nmi->pos++] = bit;
Mask bit to only 3 bits?
> + nmi->scratch[nmi->pos++] = (byte >> 4) & 0xf;
> + nmi->scratch[nmi->pos++] = byte & 0xf;
Not following how byte is split up. Figure 29 in 1.1d suggests it should be
in bits 23:08 and this doesn't match that. Perhaps a reference given I guess
I'm looking at wrong thing.
> +}
> +static void nmi_handle_mi_read_nmi_ds(NMIDevice *nmi, NMIRequest *request)
> +{
> + I2CSlave *i2c = I2C_SLAVE(nmi);
> +
> + uint32_t dw0 = le32_to_cpu(request->dw0);
> + uint8_t dtyp = (dw0 >> 24) & 0xf;
> + uint8_t *buf;
> + size_t len;
> +
> + trace_nmi_handle_mi_read_nmi_ds(dtyp);
> +
> + static uint8_t nmi_ds_subsystem[36] = {
> + 0x00, /* success */
> + 0x20, /* response data length */
Not the easiest datasheet to read, but I think length is 2 bytes.
Figure 93 in the 1.2b NMI spec has it as bits 15:00 in
a 24 bit field. Ah. I see this is 1.1 definition, in that it's
the same but in figure 89.
> + 0x00, 0x00, /* reserved */
> + 0x00, /* number of ports */
> + 0x01, /* major version */
> + 0x01, /* minor version */
> + };
> +
> + static uint8_t nmi_ds_ports[36] = {
> + 0x00, /* success */
> + 0x20, /* response data length */
As above - this is 2 bytes.
> + 0x00, 0x00, /* reserved */
> + 0x02, /* port type (smbus) */
> + 0x00, /* reserved */
> + 0x40, 0x00, /* maximum mctp transission unit size (64 bytes) */
> + 0x00, 0x00, 0x00, 0x00, /* management endpoint buffer size */
> + 0x00, 0x00, /* vpd i2c address/freq */
Give separate bytes for the two things, why not just have two lines and
a comment for each one?
> + 0x00, 0x01, /* management endpoint i2c address/freq */
Same here though second byte isn't anything to do with frequency. Documnted
as NVMe Basic Management and indicates if that command is supported.
> + };
> +
> + static uint8_t nmi_ds_empty[8] = {
> + 0x00, /* success */
> + 0x02, /* response data length */
> + 0x00, 0x00, /* reserved */
> + 0x00, 0x00, /* number of controllers */
A reference for this would be good as I'm not sure it's defined in the NMI spec.
Is it the controller list from 4.4.1 in the main NVME 2.0 spec?
> + 0x00, 0x00, /* padding */
> + };
> +
> + switch (dtyp) {
> + case NMI_CMD_READ_NMI_DS_SUBSYSTEM:
> + len = 36;
sizeof(nmi_ds_subsystem) Might as well keep that 36 in just one place.
> + buf = nmi_ds_subsystem;
> +
> + break;
> +
> + case NMI_CMD_READ_NMI_DS_PORTS:
> + len = 36;
> + buf = nmi_ds_ports;
same here?
> +
> + /* patch in the i2c address of the endpoint */
> + buf[14] = i2c->address;
If you have multiple instances of this as they will
race over the static buffer. Just make it non static and add
a comment on why.
> +
> + break;
> +
> + case NMI_CMD_READ_NMI_DS_CTRL_LIST:
> + case NMI_CMD_READ_NMI_DS_CMD_SUPPORT:
> + case NMI_CMD_READ_NMI_DS_MEB_CMD_SUPPORT:
> + len = 8;
> + buf = nmi_ds_empty;
> +
> + break;
> +
> + default:
> + nmi_set_parameter_error(nmi, offsetof(NMIRequest, dw0) + 4, 0);
> +
> + return;
> + }
> +
> + memcpy(nmi->scratch + nmi->pos, buf, len);
> + nmi->pos += len;
> +}
> +
> +enum {
> + NMI_CMD_CONFIGURATION_GET_SMBUS_FREQ = 0x1,
> + NMI_CMD_CONFIGURATION_GET_HEALTH_STATUS_CHANGE = 0x2,
> + NMI_CMD_CONFIGURATION_GET_MCTP_TRANSMISSION_UNIT = 0x3,
> +};
> +
> +static void nmi_handle_mi_config_get(NMIDevice *nmi, NMIRequest *request)
> +{
> + uint32_t dw0 = le32_to_cpu(request->dw0);
> + uint8_t identifier = dw0 & 0xff;
> + uint8_t *buf;
> +
> + static uint8_t smbus_freq[4] = {
> + 0x00, /* success */
> + 0x01, 0x00, 0x00, /* 100 kHz */
> + };
> +
> + static uint8_t mtu[4] = {
> + 0x00, /* success */
> + 0x40, 0x00, 0x00, /* 64 */
2 bytes only I think with another reserved.
Figure 66 in 1.1d
> + };
> +
> + trace_nmi_handle_mi_config_get(identifier);
> +
> + switch (identifier) {
> + case NMI_CMD_CONFIGURATION_GET_SMBUS_FREQ:
> + buf = smbus_freq;
> + break;
> +
> + case NMI_CMD_CONFIGURATION_GET_MCTP_TRANSMISSION_UNIT:
> + buf = mtu;
> + break;
> +
> + default:
> + nmi_set_parameter_error(nmi, 0x0, offsetof(NMIRequest, dw0));
> + return;
> + }
> +
> + memcpy(nmi->scratch + nmi->pos, buf, 4);
> + nmi->pos += 4;
> +}
> +
> +enum {
> + NMI_CMD_READ_NMI_DS = 0x0,
> + NMI_CMD_CONFIGURATION_GET = 0x4,
> +};
> +
> +static void nmi_handle_mi(NMIDevice *nmi, NMIMessage *msg)
> +{
> + NMIRequest *request = (NMIRequest *)msg->payload;
> +
> + trace_nmi_handle_mi(request->opc);
> +
> + switch (request->opc) {
> + case NMI_CMD_READ_NMI_DS:
> + nmi_handle_mi_read_nmi_ds(nmi, request);
> + break;
> +
> + case NMI_CMD_CONFIGURATION_GET:
> + nmi_handle_mi_config_get(nmi, request);
> + break;
> +
> + default:
> + nmi_set_parameter_error(nmi, 0x0, 0x0);
> + fprintf(stderr, "nmi command 0x%x not handled\n", request->opc);
> +
> + break;
> + }
> +}
> +
> +enum {
> + NMI_MESSAGE_TYPE_NMI = 0x1,
> +};
> +
> +static size_t nmi_get_types(MCTPI2CEndpoint *mctp, const uint8_t **data)
> +{
> + static const uint8_t buf[] = {
> + 0x0, 0x1, MCTP_MESSAGE_TYPE_NMI,
> + };
Perhaps a comment that the 0x1 is the length. Or you could define
a structure for this with a variable length final field?
Also, should the control type be reported? I couldn't find a statement
that it shouldn't and it has a message ID.
> +
> + *data = buf;
> +
> + return sizeof(buf);
> +}
> +
next prev parent reply other threads:[~2023-05-31 15:41 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-31 11:47 [PATCH v3 0/3] hw/{i2c, nvme}: mctp endpoint, nvme management interface model Klaus Jensen
2023-05-31 11:47 ` [PATCH v3 1/3] hw/i2c: add smbus pec utility function Klaus Jensen
2023-05-31 13:13 ` Jonathan Cameron via
2023-06-01 20:34 ` Philippe Mathieu-Daudé
2023-05-31 11:47 ` [PATCH v3 2/3] hw/i2c: add mctp core Klaus Jensen
2023-05-31 14:59 ` Jonathan Cameron via
2023-05-31 15:04 ` Jonathan Cameron via
2023-05-31 11:47 ` [PATCH v3 3/3] hw/nvme: add nvme management interface model Klaus Jensen
2023-05-31 15:39 ` Jonathan Cameron via [this message]
2023-06-01 19:42 ` [PATCH v3 0/3] hw/{i2c, nvme}: mctp endpoint, " Corey Minyard
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=20230531163957.0000494e@Huawei.com \
--to=qemu-devel@nongnu.org \
--cc=Jonathan.Cameron@Huawei.com \
--cc=clg@kaod.org \
--cc=cminyard@mvista.com \
--cc=gost.dev@samsung.com \
--cc=its@irrelevant.dk \
--cc=jasowang@redhat.com \
--cc=jk@codeconstruct.com.au \
--cc=k.jensen@samsung.com \
--cc=kbusch@kernel.org \
--cc=liorw@pliops.com \
--cc=matt@codeconstruct.com.au \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=peter@pjd.dev \
--cc=qemu-arm@nongnu.org \
--cc=qemu-block@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).