summaryrefslogtreecommitdiff
path: root/hw/block
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-08-05 13:05:29 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-08-05 13:05:29 +0100
commitbd8eda537fbe6f28a94db30e8facab2bf528b204 (patch)
treeffbddd89dfed1d48db6aa51aa093470d084919de /hw/block
parent8bfa87a231a846343a33bd817ea002740d84ae51 (diff)
parent47989f14472262a289894058f7babf1db37edda5 (diff)
downloadqemu-bd8eda537fbe6f28a94db30e8facab2bf528b204.tar.gz
qemu-bd8eda537fbe6f28a94db30e8facab2bf528b204.tar.bz2
qemu-bd8eda537fbe6f28a94db30e8facab2bf528b204.zip
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging
Block layer patches for 2.7.0-rc2 # gpg: Signature made Fri 05 Aug 2016 10:30:12 BST # gpg: using RSA key 0x7F09B272C88F2FD6 # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * remotes/kevin/tags/for-upstream: nvme: bump PCI revision nvme: fix identify to be NVMe 1.1 compliant block: Accept any target node for transactional blockdev-backup Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/block')
-rw-r--r--hw/block/nvme.c61
1 files changed, 53 insertions, 8 deletions
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 2ded2475ee..cef3bb42f1 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -469,19 +469,22 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd)
return NVME_SUCCESS;
}
-static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
+static uint16_t nvme_identify_ctrl(NvmeCtrl *n, NvmeIdentify *c)
+{
+ uint64_t prp1 = le64_to_cpu(c->prp1);
+ uint64_t prp2 = le64_to_cpu(c->prp2);
+
+ return nvme_dma_read_prp(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl),
+ prp1, prp2);
+}
+
+static uint16_t nvme_identify_ns(NvmeCtrl *n, NvmeIdentify *c)
{
NvmeNamespace *ns;
- NvmeIdentify *c = (NvmeIdentify *)cmd;
- uint32_t cns = le32_to_cpu(c->cns);
uint32_t nsid = le32_to_cpu(c->nsid);
uint64_t prp1 = le64_to_cpu(c->prp1);
uint64_t prp2 = le64_to_cpu(c->prp2);
- if (cns) {
- return nvme_dma_read_prp(n, (uint8_t *)&n->id_ctrl, sizeof(n->id_ctrl),
- prp1, prp2);
- }
if (nsid == 0 || nsid > n->num_namespaces) {
return NVME_INVALID_NSID | NVME_DNR;
}
@@ -491,6 +494,48 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
prp1, prp2);
}
+static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeIdentify *c)
+{
+ static const int data_len = 4096;
+ uint32_t min_nsid = le32_to_cpu(c->nsid);
+ uint64_t prp1 = le64_to_cpu(c->prp1);
+ uint64_t prp2 = le64_to_cpu(c->prp2);
+ uint32_t *list;
+ uint16_t ret;
+ int i, j = 0;
+
+ list = g_malloc0(data_len);
+ for (i = 0; i < n->num_namespaces; i++) {
+ if (i < min_nsid) {
+ continue;
+ }
+ list[j++] = cpu_to_le32(i + 1);
+ if (j == data_len / sizeof(uint32_t)) {
+ break;
+ }
+ }
+ ret = nvme_dma_read_prp(n, (uint8_t *)list, data_len, prp1, prp2);
+ g_free(list);
+ return ret;
+}
+
+
+static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
+{
+ NvmeIdentify *c = (NvmeIdentify *)cmd;
+
+ switch (le32_to_cpu(c->cns)) {
+ case 0x00:
+ return nvme_identify_ns(n, c);
+ case 0x01:
+ return nvme_identify_ctrl(n, c);
+ case 0x02:
+ return nvme_identify_nslist(n, c);
+ default:
+ return NVME_INVALID_FIELD | NVME_DNR;
+ }
+}
+
static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
{
uint32_t dw10 = le32_to_cpu(cmd->cdw10);
@@ -909,7 +954,7 @@ static void nvme_class_init(ObjectClass *oc, void *data)
pc->class_id = PCI_CLASS_STORAGE_EXPRESS;
pc->vendor_id = PCI_VENDOR_ID_INTEL;
pc->device_id = 0x5845;
- pc->revision = 1;
+ pc->revision = 2;
pc->is_express = 1;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);