|
@@ -219,7 +219,6 @@
|
|
|
#define NVME_TEMPERATURE_CRITICAL 0x175
|
|
|
#define NVME_NUM_FW_SLOTS 1
|
|
|
#define NVME_DEFAULT_MAX_ZA_SIZE (128 * KiB)
|
|
|
-#define NVME_MAX_VFS 127
|
|
|
#define NVME_VF_RES_GRANULARITY 1
|
|
|
#define NVME_VF_OFFSET 0x1
|
|
|
#define NVME_VF_STRIDE 1
|
|
@@ -4352,7 +4351,7 @@ static uint16_t nvme_io_mgmt_send_ruh_update(NvmeCtrl *n, NvmeRequest *req)
|
|
|
NvmeNamespace *ns = req->ns;
|
|
|
uint32_t cdw10 = le32_to_cpu(cmd->cdw10);
|
|
|
uint16_t ret = NVME_SUCCESS;
|
|
|
- uint32_t npid = (cdw10 >> 1) + 1;
|
|
|
+ uint32_t npid = (cdw10 >> 16) + 1;
|
|
|
unsigned int i = 0;
|
|
|
g_autofree uint16_t *pids = NULL;
|
|
|
uint32_t maxnpid;
|
|
@@ -5480,14 +5479,14 @@ static uint16_t nvme_identify_sec_ctrl_list(NvmeCtrl *n, NvmeRequest *req)
|
|
|
NvmeIdentify *c = (NvmeIdentify *)&req->cmd;
|
|
|
uint16_t pri_ctrl_id = le16_to_cpu(n->pri_ctrl_cap.cntlid);
|
|
|
uint16_t min_id = le16_to_cpu(c->ctrlid);
|
|
|
- uint8_t num_sec_ctrl = n->sec_ctrl_list.numcntl;
|
|
|
+ uint8_t num_sec_ctrl = n->nr_sec_ctrls;
|
|
|
NvmeSecCtrlList list = {0};
|
|
|
uint8_t i;
|
|
|
|
|
|
for (i = 0; i < num_sec_ctrl; i++) {
|
|
|
- if (n->sec_ctrl_list.sec[i].scid >= min_id) {
|
|
|
- list.numcntl = num_sec_ctrl - i;
|
|
|
- memcpy(&list.sec, n->sec_ctrl_list.sec + i,
|
|
|
+ if (n->sec_ctrl_list[i].scid >= min_id) {
|
|
|
+ list.numcntl = MIN(num_sec_ctrl - i, 127);
|
|
|
+ memcpy(&list.sec, n->sec_ctrl_list + i,
|
|
|
list.numcntl * sizeof(NvmeSecCtrlEntry));
|
|
|
break;
|
|
|
}
|
|
@@ -5629,6 +5628,26 @@ static uint16_t nvme_identify_nslist_csi(NvmeCtrl *n, NvmeRequest *req,
|
|
|
return nvme_c2h(n, list, data_len, req);
|
|
|
}
|
|
|
|
|
|
+static uint16_t nvme_endurance_group_list(NvmeCtrl *n, NvmeRequest *req)
|
|
|
+{
|
|
|
+ uint16_t list[NVME_CONTROLLER_LIST_SIZE] = {};
|
|
|
+ uint16_t *nr_ids = &list[0];
|
|
|
+ uint16_t *ids = &list[1];
|
|
|
+ uint16_t endgid = le32_to_cpu(req->cmd.cdw11) & 0xffff;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The current nvme-subsys only supports Endurance Group #1.
|
|
|
+ */
|
|
|
+ if (!endgid) {
|
|
|
+ *nr_ids = 1;
|
|
|
+ ids[0] = 1;
|
|
|
+ } else {
|
|
|
+ *nr_ids = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ return nvme_c2h(n, list, sizeof(list), req);
|
|
|
+}
|
|
|
+
|
|
|
static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req)
|
|
|
{
|
|
|
NvmeNamespace *ns;
|
|
@@ -5744,6 +5763,8 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req)
|
|
|
return nvme_identify_nslist(n, req, false);
|
|
|
case NVME_ID_CNS_CS_NS_ACTIVE_LIST:
|
|
|
return nvme_identify_nslist_csi(n, req, true);
|
|
|
+ case NVME_ID_CNS_ENDURANCE_GROUP_LIST:
|
|
|
+ return nvme_endurance_group_list(n, req);
|
|
|
case NVME_ID_CNS_CS_NS_PRESENT_LIST:
|
|
|
return nvme_identify_nslist_csi(n, req, false);
|
|
|
case NVME_ID_CNS_NS_DESCR_LIST:
|
|
@@ -7122,8 +7143,8 @@ static void nvme_ctrl_reset(NvmeCtrl *n, NvmeResetType rst)
|
|
|
|
|
|
if (n->params.sriov_max_vfs) {
|
|
|
if (!pci_is_vf(pci_dev)) {
|
|
|
- for (i = 0; i < n->sec_ctrl_list.numcntl; i++) {
|
|
|
- sctrl = &n->sec_ctrl_list.sec[i];
|
|
|
+ for (i = 0; i < n->nr_sec_ctrls; i++) {
|
|
|
+ sctrl = &n->sec_ctrl_list[i];
|
|
|
nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false);
|
|
|
}
|
|
|
}
|
|
@@ -7805,6 +7826,11 @@ static bool nvme_check_params(NvmeCtrl *n, Error **errp)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ if (params->mqes < 1) {
|
|
|
+ error_setg(errp, "mqes property cannot be less than 1");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
if (n->pmr.dev) {
|
|
|
if (params->msix_exclusive_bar) {
|
|
|
error_setg(errp, "not enough BARs available to enable PMR");
|
|
@@ -7842,12 +7868,6 @@ static bool nvme_check_params(NvmeCtrl *n, Error **errp)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- if (params->sriov_max_vfs > NVME_MAX_VFS) {
|
|
|
- error_setg(errp, "sriov_max_vfs must be between 0 and %d",
|
|
|
- NVME_MAX_VFS);
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
if (params->cmb_size_mb) {
|
|
|
error_setg(errp, "CMB is not supported with SR-IOV");
|
|
|
return false;
|
|
@@ -7912,7 +7932,7 @@ static bool nvme_check_params(NvmeCtrl *n, Error **errp)
|
|
|
static void nvme_init_state(NvmeCtrl *n)
|
|
|
{
|
|
|
NvmePriCtrlCap *cap = &n->pri_ctrl_cap;
|
|
|
- NvmeSecCtrlList *list = &n->sec_ctrl_list;
|
|
|
+ NvmeSecCtrlEntry *list = n->sec_ctrl_list;
|
|
|
NvmeSecCtrlEntry *sctrl;
|
|
|
PCIDevice *pci = PCI_DEVICE(n);
|
|
|
uint8_t max_vfs;
|
|
@@ -7937,9 +7957,9 @@ static void nvme_init_state(NvmeCtrl *n)
|
|
|
n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1);
|
|
|
QTAILQ_INIT(&n->aer_queue);
|
|
|
|
|
|
- list->numcntl = max_vfs;
|
|
|
+ n->nr_sec_ctrls = max_vfs;
|
|
|
for (i = 0; i < max_vfs; i++) {
|
|
|
- sctrl = &list->sec[i];
|
|
|
+ sctrl = &list[i];
|
|
|
sctrl->pcid = cpu_to_le16(n->cntlid);
|
|
|
sctrl->vfn = cpu_to_le16(i + 1);
|
|
|
}
|
|
@@ -8099,6 +8119,7 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
|
|
|
uint8_t *pci_conf = pci_dev->config;
|
|
|
uint64_t bar_size;
|
|
|
unsigned msix_table_offset = 0, msix_pba_offset = 0;
|
|
|
+ unsigned nr_vectors;
|
|
|
int ret;
|
|
|
|
|
|
pci_conf[PCI_INTERRUPT_PIN] = 1;
|
|
@@ -8131,9 +8152,19 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
|
|
|
assert(n->params.msix_qsize >= 1);
|
|
|
|
|
|
/* add one to max_ioqpairs to account for the admin queue pair */
|
|
|
- bar_size = nvme_mbar_size(n->params.max_ioqpairs + 1,
|
|
|
- n->params.msix_qsize, &msix_table_offset,
|
|
|
- &msix_pba_offset);
|
|
|
+ if (!pci_is_vf(pci_dev)) {
|
|
|
+ nr_vectors = n->params.msix_qsize;
|
|
|
+ bar_size = nvme_mbar_size(n->params.max_ioqpairs + 1,
|
|
|
+ nr_vectors, &msix_table_offset,
|
|
|
+ &msix_pba_offset);
|
|
|
+ } else {
|
|
|
+ NvmeCtrl *pn = NVME(pcie_sriov_get_pf(pci_dev));
|
|
|
+ NvmePriCtrlCap *cap = &pn->pri_ctrl_cap;
|
|
|
+
|
|
|
+ nr_vectors = le16_to_cpu(cap->vifrsm);
|
|
|
+ bar_size = nvme_mbar_size(le16_to_cpu(cap->vqfrsm), nr_vectors,
|
|
|
+ &msix_table_offset, &msix_pba_offset);
|
|
|
+ }
|
|
|
|
|
|
memory_region_init(&n->bar0, OBJECT(n), "nvme-bar0", bar_size);
|
|
|
memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, "nvme",
|
|
@@ -8147,7 +8178,7 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp)
|
|
|
PCI_BASE_ADDRESS_MEM_TYPE_64, &n->bar0);
|
|
|
}
|
|
|
|
|
|
- ret = msix_init(pci_dev, n->params.msix_qsize,
|
|
|
+ ret = msix_init(pci_dev, nr_vectors,
|
|
|
&n->bar0, 0, msix_table_offset,
|
|
|
&n->bar0, 0, msix_pba_offset, 0, errp);
|
|
|
}
|
|
@@ -8289,7 +8320,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
|
|
|
|
|
|
id->ctratt = cpu_to_le32(ctratt);
|
|
|
|
|
|
- NVME_CAP_SET_MQES(cap, 0x7ff);
|
|
|
+ NVME_CAP_SET_MQES(cap, n->params.mqes);
|
|
|
NVME_CAP_SET_CQR(cap, 1);
|
|
|
NVME_CAP_SET_TO(cap, 0xf);
|
|
|
NVME_CAP_SET_CSS(cap, NVME_CAP_CSS_NVM);
|
|
@@ -8448,17 +8479,18 @@ static Property nvme_props[] = {
|
|
|
DEFINE_PROP_UINT8("zoned.zasl", NvmeCtrl, params.zasl, 0),
|
|
|
DEFINE_PROP_BOOL("zoned.auto_transition", NvmeCtrl,
|
|
|
params.auto_transition_zones, true),
|
|
|
- DEFINE_PROP_UINT8("sriov_max_vfs", NvmeCtrl, params.sriov_max_vfs, 0),
|
|
|
+ DEFINE_PROP_UINT16("sriov_max_vfs", NvmeCtrl, params.sriov_max_vfs, 0),
|
|
|
DEFINE_PROP_UINT16("sriov_vq_flexible", NvmeCtrl,
|
|
|
params.sriov_vq_flexible, 0),
|
|
|
DEFINE_PROP_UINT16("sriov_vi_flexible", NvmeCtrl,
|
|
|
params.sriov_vi_flexible, 0),
|
|
|
- DEFINE_PROP_UINT8("sriov_max_vi_per_vf", NvmeCtrl,
|
|
|
- params.sriov_max_vi_per_vf, 0),
|
|
|
- DEFINE_PROP_UINT8("sriov_max_vq_per_vf", NvmeCtrl,
|
|
|
- params.sriov_max_vq_per_vf, 0),
|
|
|
+ DEFINE_PROP_UINT32("sriov_max_vi_per_vf", NvmeCtrl,
|
|
|
+ params.sriov_max_vi_per_vf, 0),
|
|
|
+ DEFINE_PROP_UINT32("sriov_max_vq_per_vf", NvmeCtrl,
|
|
|
+ params.sriov_max_vq_per_vf, 0),
|
|
|
DEFINE_PROP_BOOL("msix-exclusive-bar", NvmeCtrl, params.msix_exclusive_bar,
|
|
|
false),
|
|
|
+ DEFINE_PROP_UINT16("mqes", NvmeCtrl, params.mqes, 0x7ff),
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
|
};
|
|
|
|
|
@@ -8520,7 +8552,7 @@ static void nvme_sriov_post_write_config(PCIDevice *dev, uint16_t old_num_vfs)
|
|
|
int i;
|
|
|
|
|
|
for (i = pcie_sriov_num_vfs(dev); i < old_num_vfs; i++) {
|
|
|
- sctrl = &n->sec_ctrl_list.sec[i];
|
|
|
+ sctrl = &n->sec_ctrl_list[i];
|
|
|
nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false);
|
|
|
}
|
|
|
}
|