hw/nvme: Add support for Primary Controller Capabilities
Implementation of Primary Controller Capabilities data structure (Identify command with CNS value of 14h). Currently, the command returns only ID of a primary controller. Handling of remaining fields are added in subsequent patches implementing virtualization enhancements. Signed-off-by: Lukasz Maniak <lukasz.maniak@linux.intel.com> Reviewed-by: Klaus Jensen <k.jensen@samsung.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
This commit is contained in:
parent
44c2c09488
commit
5e6f963f01
@ -4804,6 +4804,14 @@ static uint16_t nvme_identify_ctrl_list(NvmeCtrl *n, NvmeRequest *req,
|
||||
return nvme_c2h(n, (uint8_t *)list, sizeof(list), req);
|
||||
}
|
||||
|
||||
static uint16_t nvme_identify_pri_ctrl_cap(NvmeCtrl *n, NvmeRequest *req)
|
||||
{
|
||||
trace_pci_nvme_identify_pri_ctrl_cap(le16_to_cpu(n->pri_ctrl_cap.cntlid));
|
||||
|
||||
return nvme_c2h(n, (uint8_t *)&n->pri_ctrl_cap,
|
||||
sizeof(NvmePriCtrlCap), req);
|
||||
}
|
||||
|
||||
static uint16_t nvme_identify_ns_csi(NvmeCtrl *n, NvmeRequest *req,
|
||||
bool active)
|
||||
{
|
||||
@ -5020,6 +5028,8 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeRequest *req)
|
||||
return nvme_identify_ctrl_list(n, req, true);
|
||||
case NVME_ID_CNS_CTRL_LIST:
|
||||
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_CS_NS:
|
||||
return nvme_identify_ns_csi(n, req, true);
|
||||
case NVME_ID_CNS_CS_NS_PRESENT:
|
||||
@ -6611,6 +6621,8 @@ static void nvme_check_constraints(NvmeCtrl *n, Error **errp)
|
||||
|
||||
static void nvme_init_state(NvmeCtrl *n)
|
||||
{
|
||||
NvmePriCtrlCap *cap = &n->pri_ctrl_cap;
|
||||
|
||||
/* add one to max_ioqpairs to account for the admin queue pair */
|
||||
n->reg_size = pow2ceil(sizeof(NvmeBar) +
|
||||
2 * (n->params.max_ioqpairs + 1) * NVME_DB_SIZE);
|
||||
@ -6620,6 +6632,8 @@ static void nvme_init_state(NvmeCtrl *n)
|
||||
n->features.temp_thresh_hi = NVME_TEMPERATURE_WARNING;
|
||||
n->starttime_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
|
||||
n->aer_reqs = g_new0(NvmeRequest *, n->params.aerl + 1);
|
||||
|
||||
cap->cntlid = cpu_to_le16(n->cntlid);
|
||||
}
|
||||
|
||||
static void nvme_init_cmb(NvmeCtrl *n, PCIDevice *pci_dev)
|
||||
@ -6921,15 +6935,14 @@ static void nvme_realize(PCIDevice *pci_dev, Error **errp)
|
||||
qbus_init(&n->bus, sizeof(NvmeBus), TYPE_NVME_BUS,
|
||||
&pci_dev->qdev, n->parent_obj.qdev.id);
|
||||
|
||||
nvme_init_state(n);
|
||||
if (nvme_init_pci(n, pci_dev, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvme_init_subsys(n, errp)) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
nvme_init_state(n);
|
||||
if (nvme_init_pci(n, pci_dev, errp)) {
|
||||
return;
|
||||
}
|
||||
nvme_init_ctrl(n, pci_dev);
|
||||
|
||||
/* setup a namespace if the controller drive property was given */
|
||||
|
@ -478,6 +478,8 @@ typedef struct NvmeCtrl {
|
||||
uint32_t async_config;
|
||||
NvmeHostBehaviorSupport hbs;
|
||||
} features;
|
||||
|
||||
NvmePriCtrlCap pri_ctrl_cap;
|
||||
} NvmeCtrl;
|
||||
|
||||
static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
|
||||
|
@ -56,6 +56,7 @@ pci_nvme_identify_ctrl(void) "identify controller"
|
||||
pci_nvme_identify_ctrl_csi(uint8_t csi) "identify controller, csi=0x%"PRIx8""
|
||||
pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32""
|
||||
pci_nvme_identify_ctrl_list(uint8_t cns, uint16_t cntid) "cns 0x%"PRIx8" cntid %"PRIu16""
|
||||
pci_nvme_identify_pri_ctrl_cap(uint16_t cntlid) "identify primary controller capabilities cntlid=%"PRIu16""
|
||||
pci_nvme_identify_ns_csi(uint32_t ns, uint8_t csi) "nsid=%"PRIu32", csi=0x%"PRIx8""
|
||||
pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32""
|
||||
pci_nvme_identify_nslist_csi(uint16_t ns, uint8_t csi) "nsid=%"PRIu16", csi=0x%"PRIx8""
|
||||
|
@ -1033,6 +1033,7 @@ enum NvmeIdCns {
|
||||
NVME_ID_CNS_NS_PRESENT = 0x11,
|
||||
NVME_ID_CNS_NS_ATTACHED_CTRL_LIST = 0x12,
|
||||
NVME_ID_CNS_CTRL_LIST = 0x13,
|
||||
NVME_ID_CNS_PRIMARY_CTRL_CAP = 0x14,
|
||||
NVME_ID_CNS_CS_NS_PRESENT_LIST = 0x1a,
|
||||
NVME_ID_CNS_CS_NS_PRESENT = 0x1b,
|
||||
NVME_ID_CNS_IO_COMMAND_SET = 0x1c,
|
||||
@ -1553,6 +1554,27 @@ typedef enum NvmeZoneState {
|
||||
NVME_ZONE_STATE_OFFLINE = 0x0f,
|
||||
} NvmeZoneState;
|
||||
|
||||
typedef struct QEMU_PACKED NvmePriCtrlCap {
|
||||
uint16_t cntlid;
|
||||
uint16_t portid;
|
||||
uint8_t crt;
|
||||
uint8_t rsvd5[27];
|
||||
uint32_t vqfrt;
|
||||
uint32_t vqrfa;
|
||||
uint16_t vqrfap;
|
||||
uint16_t vqprt;
|
||||
uint16_t vqfrsm;
|
||||
uint16_t vqgran;
|
||||
uint8_t rsvd48[16];
|
||||
uint32_t vifrt;
|
||||
uint32_t virfa;
|
||||
uint16_t virfap;
|
||||
uint16_t viprt;
|
||||
uint16_t vifrsm;
|
||||
uint16_t vigran;
|
||||
uint8_t rsvd80[4016];
|
||||
} NvmePriCtrlCap;
|
||||
|
||||
static inline void _nvme_check_size(void)
|
||||
{
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeBar) != 4096);
|
||||
@ -1588,5 +1610,6 @@ static inline void _nvme_check_size(void)
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeIdNsDescr) != 4);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeZoneDescr) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeDifTuple) != 16);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmePriCtrlCap) != 4096);
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user