mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
hw/nvme: Add support for Secondary Controller List
Introduce handling for Secondary Controller List (Identify command with CNS value of 15h). Secondary controller ids are unique in the subsystem, hence they are reserved by it upon initialization of the primary controller to the number of sriov_max_vfs. ID reservation requires the addition of an intermediate controller slot state, so the reserved controller has the address 0xFFFF. A secondary controller is in the reserved state when it has no virtual function assigned, but its primary controller is realized. Secondary controller reservations are released to NULL when its primary controller is unregistered. Signed-off-by: Lukasz Maniak <lukasz.maniak@linux.intel.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Klaus Jensen <k.jensen@samsung.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
This commit is contained in:
parent
5e6f963f01
commit
99f48ae7ae
6 changed files with 141 additions and 10 deletions
|
@ -4812,6 +4812,29 @@ static uint16_t nvme_identify_pri_ctrl_cap(NvmeCtrl *n, NvmeRequest *req)
|
|||
sizeof(NvmePriCtrlCap), req);
|
||||
}
|
||||
|
||||
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;
|
||||
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,
|
||||
list.numcntl * sizeof(NvmeSecCtrlEntry));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
trace_pci_nvme_identify_sec_ctrl_list(pri_ctrl_id, list.numcntl);
|
||||
|
||||
return nvme_c2h(n, (uint8_t *)&list, sizeof(list), req);
|
||||
}
|
||||
|
||||
static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req,
|
||||
bool active)
|
||||
{
|
||||
|
@ -5030,6 +5053,8 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req)
|
|||
return nvme_identify_ctrl_list(n, req, false);
|
||||
case NVME_ID_CNS_PRIMARY_CTRL_CAP:
|
||||
return nvme_identify_pri_ctrl_cap(n, req);
|
||||
case NVME_ID_CNS_SECONDARY_CTRL_LIST:
|
||||
return nvme_identify_sec_ctrl_list(n, req);
|
||||
case NVME_ID_CNS_CS_NS:
|
||||
return nvme_identify_ns_csi(n, req, true);
|
||||
case NVME_ID_CNS_CS_NS_PRESENT:
|
||||
|
@ -6622,6 +6647,9 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
|
|||
static void nvme_init_state(NvmeCtrl *n)
|
||||
{
|
||||
NvmePriCtrlCap *cap = &n->pri_ctrl_cap;
|
||||
NvmeSecCtrlList *list = &n->sec_ctrl_list;
|
||||
NvmeSecCtrlEntry *sctrl;
|
||||
int i;
|
||||
|
||||
/* add one to max_ioqpairs to account for the admin queue pair */
|
||||
n->reg_size = pow2ceil(sizeof(NvmeBar) +
|
||||
|
@ -6633,6 +6661,13 @@ static void nvme_init_state(NvmeCtrl *n)
|
|||
n->starttime_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
|
||||
n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1);
|
||||
|
||||
list->numcntl = cpu_to_le16(n->params.sriov_max_vfs);
|
||||
for (i = 0; i < n->params.sriov_max_vfs; i++) {
|
||||
sctrl = &list->sec[i];
|
||||
sctrl->pcid = cpu_to_le16(n->cntlid);
|
||||
sctrl->vfn = cpu_to_le16(i + 1);
|
||||
}
|
||||
|
||||
cap->cntlid = cpu_to_le16(n->cntlid);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue