[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 2/2] hw/block/nvme: add nvme telemetry log support
From: |
Klaus Jensen |
Subject: |
[PATCH 2/2] hw/block/nvme: add nvme telemetry log support |
Date: |
Mon, 8 Feb 2021 15:10:12 +0100 |
From: Gollu Appalanaidu <anaidu.gollu@samsung.com>
This adds basic support for Telemetry Host Initiated and Controller
Initiated log pages. The controller does not record any telemetry but
provides the log pages.
Signed-off-by: Gollu Appalanaidu <anaidu.gollu@samsung.com>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
---
include/block/nvme.h | 23 ++++++++++++++++++++---
hw/block/nvme.c | 33 ++++++++++++++++++++++++++++++++-
hw/block/trace-events | 1 +
3 files changed, 53 insertions(+), 4 deletions(-)
diff --git a/include/block/nvme.h b/include/block/nvme.h
index f82b5ffc2c1d..95ffe4412679 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -922,6 +922,19 @@ typedef struct NvmeEffectsLog {
uint8_t resv[2048];
} NvmeEffectsLog;
+typedef struct NvmeTelemetry {
+ uint8_t lid;
+ uint8_t rsvd1[4];
+ uint8_t ieee[3];
+ uint16_t tda1lb;
+ uint16_t tda2lb;
+ uint16_t tda3lb;
+ uint8_t rsvd14[368];
+ uint8_t tda;
+ uint8_t tdgn;
+ uint8_t ri[128];
+} NvmeTelemetry;
+
enum {
NVME_CMD_EFF_CSUPP = 1 << 0,
NVME_CMD_EFF_LBCC = 1 << 1,
@@ -937,6 +950,8 @@ enum NvmeLogIdentifier {
NVME_LOG_SMART_INFO = 0x02,
NVME_LOG_FW_SLOT_INFO = 0x03,
NVME_LOG_CMD_EFFECTS = 0x05,
+ NVME_LOG_TEL_HOST_INIT = 0x07,
+ NVME_LOG_TEL_CTRL_INIT = 0x08,
};
typedef struct QEMU_PACKED NvmePSD {
@@ -1067,9 +1082,10 @@ enum NvmeIdCtrlFrmw {
};
enum NvmeIdCtrlLpa {
- NVME_LPA_NS_SMART = 1 << 0,
- NVME_LPA_CSE = 1 << 1,
- NVME_LPA_EXTENDED = 1 << 2,
+ NVME_LPA_NS_SMART = 1 << 0,
+ NVME_LPA_CSE = 1 << 1,
+ NVME_LPA_EXTENDED = 1 << 2,
+ NVME_LPA_TELEMETRY = 1 << 3,
};
enum NvmeIdCtrlCmic {
@@ -1395,5 +1411,6 @@ static inline void _nvme_check_size(void)
QEMU_BUILD_BUG_ON(sizeof(NvmeSglDescriptor) != 16);
QEMU_BUILD_BUG_ON(sizeof(NvmeIdNsDescr) != 4);
QEMU_BUILD_BUG_ON(sizeof(NvmeZoneDescr) != 64);
+ QEMU_BUILD_BUG_ON(sizeof(NvmeTelemetry) != 512);
}
#endif
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 547a3073ef1b..01b92a6f66c8 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2908,6 +2908,33 @@ static uint16_t nvme_cmd_effects(NvmeCtrl *n, uint8_t
csi, uint32_t buf_len,
DMA_DIRECTION_FROM_DEVICE, req);
}
+static uint16_t nvme_telemetry(NvmeCtrl *n, uint8_t lid, uint32_t buf_len,
+ uint64_t off, NvmeRequest *req)
+{
+ NvmeTelemetry telemetry = {
+ .lid = lid,
+ .ieee[0] = 0x00,
+ .ieee[1] = 0x54,
+ .ieee[2] = 0x52,
+ };
+
+ uint32_t trans_len;
+
+ if (buf_len & 0x1ff || off & 0x1ff) {
+ trace_pci_nvme_telemetry_log_invalid(buf_len, off);
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ if (off >= sizeof(telemetry)) {
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+
+ trans_len = MIN(sizeof(telemetry) - off, buf_len);
+
+ return nvme_dma(n, (uint8_t *)&telemetry + off, trans_len,
+ DMA_DIRECTION_FROM_DEVICE, req);
+}
+
static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req)
{
NvmeCmd *cmd = &req->cmd;
@@ -2954,6 +2981,9 @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest
*req)
return nvme_fw_log_info(n, len, off, req);
case NVME_LOG_CMD_EFFECTS:
return nvme_cmd_effects(n, csi, len, off, req);
+ case NVME_LOG_TEL_HOST_INIT:
+ case NVME_LOG_TEL_CTRL_INIT:
+ return nvme_telemetry(n, lid, len, off, req);
default:
trace_pci_nvme_err_invalid_log_page(nvme_cid(req), lid);
return NVME_INVALID_FIELD | NVME_DNR;
@@ -4707,7 +4737,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice
*pci_dev)
id->acl = 3;
id->aerl = n->params.aerl;
id->frmw = (NVME_NUM_FW_SLOTS << 1) | NVME_FRMW_SLOT1_RO;
- id->lpa = NVME_LPA_NS_SMART | NVME_LPA_CSE | NVME_LPA_EXTENDED;
+ id->lpa = NVME_LPA_NS_SMART | NVME_LPA_CSE | NVME_LPA_EXTENDED |
+ NVME_LPA_TELEMETRY;
/* recommended default value (~70 C) */
id->wctemp = cpu_to_le16(NVME_TEMPERATURE_WARNING);
diff --git a/hw/block/trace-events b/hw/block/trace-events
index b6e972d733a6..500d991a0a14 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -110,6 +110,7 @@ pci_nvme_set_descriptor_extension(uint64_t slba, uint32_t
zone_idx) "set zone de
pci_nvme_zd_extension_set(uint32_t zone_idx) "set descriptor extension for
zone_idx=%"PRIu32""
pci_nvme_clear_ns_close(uint32_t state, uint64_t slba) "zone state=%"PRIu32",
slba=%"PRIu64" transitioned to Closed state"
pci_nvme_clear_ns_reset(uint32_t state, uint64_t slba) "zone state=%"PRIu32",
slba=%"PRIu64" transitioned to Empty state"
+pci_nvme_telemetry_log_invalid(size_t len, uint64_t offset) "len %zu offset
%"PRIu64""
# nvme traces for error conditions
pci_nvme_err_mdts(uint16_t cid, size_t len) "cid %"PRIu16" len %zu"
--
2.30.0