mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 01:03:55 -06:00
hw/nvme: add basic endurance group support
Add the mandatory Endurance Group identify data structures and log pages. For now, all namespaces in a subsystem belongs to a single Endurance Group. Reviewed-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
This commit is contained in:
parent
534a93d3a0
commit
771dbc3ac4
4 changed files with 93 additions and 8 deletions
|
@ -4454,6 +4454,48 @@ static uint16_t nvme_smart_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len,
|
|||
return nvme_c2h(n, (uint8_t *) &smart + off, trans_len, req);
|
||||
}
|
||||
|
||||
static uint16_t nvme_endgrp_info(NvmeCtrl *n, uint8_t rae, uint32_t buf_len,
|
||||
uint64_t off, NvmeRequest *req)
|
||||
{
|
||||
uint32_t dw11 = le32_to_cpu(req->cmd.cdw11);
|
||||
uint16_t endgrpid = (dw11 >> 16) & 0xffff;
|
||||
struct nvme_stats stats = {};
|
||||
NvmeEndGrpLog info = {};
|
||||
int i;
|
||||
|
||||
if (!n->subsys || endgrpid != 0x1) {
|
||||
return NVME_INVALID_FIELD | NVME_DNR;
|
||||
}
|
||||
|
||||
if (off >= sizeof(info)) {
|
||||
return NVME_INVALID_FIELD | NVME_DNR;
|
||||
}
|
||||
|
||||
for (i = 1; i <= NVME_MAX_NAMESPACES; i++) {
|
||||
NvmeNamespace *ns = nvme_subsys_ns(n->subsys, i);
|
||||
if (!ns) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nvme_set_blk_stats(ns, &stats);
|
||||
}
|
||||
|
||||
info.data_units_read[0] =
|
||||
cpu_to_le64(DIV_ROUND_UP(stats.units_read / 1000000000, 1000000000));
|
||||
info.data_units_written[0] =
|
||||
cpu_to_le64(DIV_ROUND_UP(stats.units_written / 1000000000, 1000000000));
|
||||
info.media_units_written[0] =
|
||||
cpu_to_le64(DIV_ROUND_UP(stats.units_written / 1000000000, 1000000000));
|
||||
|
||||
info.host_read_commands[0] = cpu_to_le64(stats.read_commands);
|
||||
info.host_write_commands[0] = cpu_to_le64(stats.write_commands);
|
||||
|
||||
buf_len = MIN(sizeof(info) - off, buf_len);
|
||||
|
||||
return nvme_c2h(n, (uint8_t *)&info + off, buf_len, req);
|
||||
}
|
||||
|
||||
|
||||
static uint16_t nvme_fw_log_info(NvmeCtrl *n, uint32_t buf_len, uint64_t off,
|
||||
NvmeRequest *req)
|
||||
{
|
||||
|
@ -4626,6 +4668,8 @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req)
|
|||
return nvme_changed_nslist(n, rae, len, off, req);
|
||||
case NVME_LOG_CMD_EFFECTS:
|
||||
return nvme_cmd_effects(n, csi, len, off, req);
|
||||
case NVME_LOG_ENDGRP:
|
||||
return nvme_endgrp_info(n, rae, len, off, req);
|
||||
default:
|
||||
trace_pci_nvme_err_invalid_log_page(nvme_cid(req), lid);
|
||||
return NVME_INVALID_FIELD | NVME_DNR;
|
||||
|
@ -7382,6 +7426,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
|
|||
uint8_t *pci_conf = pci_dev->config;
|
||||
uint64_t cap = ldq_le_p(&n->bar.cap);
|
||||
NvmeSecCtrlEntry *sctrl = nvme_sctrl(n);
|
||||
uint32_t ctratt;
|
||||
|
||||
id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID));
|
||||
id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID));
|
||||
|
@ -7392,7 +7437,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
|
|||
id->cntlid = cpu_to_le16(n->cntlid);
|
||||
|
||||
id->oaes = cpu_to_le32(NVME_OAES_NS_ATTR);
|
||||
id->ctratt |= cpu_to_le32(NVME_CTRATT_ELBAS);
|
||||
ctratt = NVME_CTRATT_ELBAS;
|
||||
|
||||
id->rab = 6;
|
||||
|
||||
|
@ -7459,8 +7504,13 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
|
|||
|
||||
if (n->subsys) {
|
||||
id->cmic |= NVME_CMIC_MULTI_CTRL;
|
||||
ctratt |= NVME_CTRATT_ENDGRPS;
|
||||
|
||||
id->endgidmax = cpu_to_le16(0x1);
|
||||
}
|
||||
|
||||
id->ctratt = cpu_to_le32(ctratt);
|
||||
|
||||
NVME_CAP_SET_MQES(cap, 0x7ff);
|
||||
NVME_CAP_SET_CQR(cap, 1);
|
||||
NVME_CAP_SET_TO(cap, 0xf);
|
||||
|
|
|
@ -592,6 +592,8 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
|
|||
if (subsys) {
|
||||
subsys->namespaces[nsid] = ns;
|
||||
|
||||
ns->id_ns.endgid = cpu_to_le16(0x1);
|
||||
|
||||
if (ns->params.detached) {
|
||||
return;
|
||||
}
|
||||
|
@ -607,6 +609,7 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nvme_attach_ns(n, ns);
|
||||
|
|
|
@ -45,6 +45,10 @@ typedef struct NvmeBus {
|
|||
OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS)
|
||||
#define SUBSYS_SLOT_RSVD (void *)0xFFFF
|
||||
|
||||
typedef struct NvmeEnduranceGroup {
|
||||
uint8_t event_conf;
|
||||
} NvmeEnduranceGroup;
|
||||
|
||||
typedef struct NvmeSubsystem {
|
||||
DeviceState parent_obj;
|
||||
NvmeBus bus;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue